From 445fee41b3925c4bd8272068e432263ec06d378c Mon Sep 17 00:00:00 2001 From: Joel Juarez Date: Sun, 30 Dec 2018 23:38:13 +0100 Subject: [PATCH 001/496] java web application without web.xml - servlets 3.0 --- javax-servlets-3/.gitignore | 6 +++ javax-servlets-3/Dockerfile | 2 + javax-servlets-3/README.md | 9 ++++ javax-servlets-3/pom.xml | 51 +++++++++++++++++++ .../servlets3/spring/AppInitializer.java | 27 ++++++++++ .../servlets3/spring/config/AppConfig.java | 11 ++++ .../controllers/UppercaseController.java | 17 +++++++ .../web/filters/EmptyParamFilter.java | 44 ++++++++++++++++ .../servlets3/web/listeners/AppListener.java | 21 ++++++++ .../web/listeners/RequestListener.java | 24 +++++++++ .../web/servlets/CounterServlet.java | 27 ++++++++++ .../web/servlets/UppercaseServlet.java | 26 ++++++++++ 12 files changed, 265 insertions(+) create mode 100644 javax-servlets-3/.gitignore create mode 100644 javax-servlets-3/Dockerfile create mode 100644 javax-servlets-3/README.md create mode 100644 javax-servlets-3/pom.xml create mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/AppInitializer.java create mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/config/AppConfig.java create mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/controllers/UppercaseController.java create mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java create mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/AppListener.java create mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/RequestListener.java create mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/CounterServlet.java create mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/UppercaseServlet.java diff --git a/javax-servlets-3/.gitignore b/javax-servlets-3/.gitignore new file mode 100644 index 0000000000..dfbd063287 --- /dev/null +++ b/javax-servlets-3/.gitignore @@ -0,0 +1,6 @@ +# Created by .ignore support plugin (hsz.mobi) +.idea +classes +target +*.iml +out \ No newline at end of file diff --git a/javax-servlets-3/Dockerfile b/javax-servlets-3/Dockerfile new file mode 100644 index 0000000000..97cc1897dd --- /dev/null +++ b/javax-servlets-3/Dockerfile @@ -0,0 +1,2 @@ +FROM tomcat +ADD ./target/javax-servlets-3-1.0-SNAPSHOT.war /usr/local/tomcat/webapps/ \ No newline at end of file diff --git a/javax-servlets-3/README.md b/javax-servlets-3/README.md new file mode 100644 index 0000000000..ff310b5928 --- /dev/null +++ b/javax-servlets-3/README.md @@ -0,0 +1,9 @@ +## Build with maven: +mvn package + +## Run with Tomcat on Docker container: +docker build --tag my-tomcat . +docker run -it --rm -p 8080:8080 my-tomcat + +### Relevant Articles: +- [Java Web Application Without Web.xml] diff --git a/javax-servlets-3/pom.xml b/javax-servlets-3/pom.xml new file mode 100644 index 0000000000..2b4fc37fc4 --- /dev/null +++ b/javax-servlets-3/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + javax-servlets-3 + 1.0-SNAPSHOT + javax-servlets-3 + war + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + + + org.springframework + spring-webmvc + ${spring.version} + + + + 4.0.1 + 5.1.3.RELEASE + + + + + org.apache.maven.plugins + maven-war-plugin + 3.1.0 + + + default-war + prepare-package + + false + + + + + + + diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/AppInitializer.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/AppInitializer.java new file mode 100644 index 0000000000..837d439cf4 --- /dev/null +++ b/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/AppInitializer.java @@ -0,0 +1,27 @@ +package com.baeldung.servlets3.spring; + +import com.baeldung.servlets3.spring.config.AppConfig; +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +public class AppInitializer implements WebApplicationInitializer { + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.register(AppConfig.class); + + servletContext.addListener(new ContextLoaderListener(context)); + + ServletRegistration.Dynamic dispatcher = servletContext.addServlet("spring-dispatcher", + new DispatcherServlet(context)); + + dispatcher.setLoadOnStartup(1); + dispatcher.addMapping("/spring/*"); + } +} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/config/AppConfig.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/config/AppConfig.java new file mode 100644 index 0000000000..0088bad770 --- /dev/null +++ b/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/config/AppConfig.java @@ -0,0 +1,11 @@ +package com.baeldung.servlets3.spring.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +@Configuration +@EnableWebMvc +@ComponentScan("com.baeldung.servlets3.spring") +public class AppConfig { +} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/controllers/UppercaseController.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/controllers/UppercaseController.java new file mode 100644 index 0000000000..74585e6b5e --- /dev/null +++ b/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/controllers/UppercaseController.java @@ -0,0 +1,17 @@ +package com.baeldung.servlets3.spring.controllers; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/uppercase") +public class UppercaseController { + + @GetMapping(produces = "text/html") + public String getUppercase(@RequestParam(required = false)String param) { + String response = param != null ? param.toUpperCase() : "Missing param"; + return "From Spring: " + response; + } +} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java new file mode 100644 index 0000000000..2c9f603d2c --- /dev/null +++ b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java @@ -0,0 +1,44 @@ +package com.baeldung.servlets3.web.filters; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import java.io.IOException; +import java.io.PrintWriter; + +@WebFilter(servletNames = { "uppercaseServlet" }, filterName = "emptyParamFilter") +public class EmptyParamFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, + FilterChain filterChain) throws IOException, ServletException { + String inputString = servletRequest.getParameter("input"); + + if (inputString == null || inputString.isEmpty()) { + response(servletResponse); + } else { + filterChain.doFilter(servletRequest, servletResponse); + } + } + + private void response(ServletResponse response) throws IOException { + response.setContentType("text/html"); + + PrintWriter out = response.getWriter(); + + out.println("Missing input parameter"); + } + + @Override + public void destroy() { + } + +} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/AppListener.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/AppListener.java new file mode 100644 index 0000000000..d61af65c31 --- /dev/null +++ b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/AppListener.java @@ -0,0 +1,21 @@ +package com.baeldung.servlets3.web.listeners; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class AppListener implements ServletContextListener { + + @Override + public void contextInitialized(ServletContextEvent event) { + ServletContext context = event.getServletContext(); + context.setAttribute("counter", 0); + } + + @Override + public void contextDestroyed(ServletContextEvent event) { + + } +} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/RequestListener.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/RequestListener.java new file mode 100644 index 0000000000..aeebf482fb --- /dev/null +++ b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/RequestListener.java @@ -0,0 +1,24 @@ +package com.baeldung.servlets3.web.listeners; + +import javax.servlet.ServletContext; +import javax.servlet.ServletRequestEvent; +import javax.servlet.ServletRequestListener; +import javax.servlet.annotation.WebListener; +import javax.servlet.http.HttpServletRequest; + +@WebListener +public class RequestListener implements ServletRequestListener { + + @Override + public void requestInitialized(ServletRequestEvent event) { + } + + @Override + public void requestDestroyed(ServletRequestEvent event) { + HttpServletRequest request = (HttpServletRequest)event.getServletRequest(); + if (!request.getServletPath().equals("/counter")) { + ServletContext context = event.getServletContext(); + context.setAttribute("counter", (int)context.getAttribute("counter") + 1); + } + } +} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/CounterServlet.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/CounterServlet.java new file mode 100644 index 0000000000..4bb92bbf77 --- /dev/null +++ b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/CounterServlet.java @@ -0,0 +1,27 @@ +package com.baeldung.servlets3.web.servlets; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +@WebServlet(urlPatterns = "/counter", name = "counterServlet") +public class CounterServlet extends HttpServlet { + + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { + doGet(request, response); + } + + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + response.setContentType("text/html"); + + PrintWriter out = response.getWriter(); + + int count = (int)request.getServletContext().getAttribute("counter"); + + out.println("Request counter: " + count); + } + +} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/UppercaseServlet.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/UppercaseServlet.java new file mode 100644 index 0000000000..9b948cd994 --- /dev/null +++ b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/UppercaseServlet.java @@ -0,0 +1,26 @@ +package com.baeldung.servlets3.web.servlets; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +@WebServlet(urlPatterns = "/uppercase", name = "uppercaseServlet") +public class UppercaseServlet extends HttpServlet { + + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { + doGet(request, response); + } + + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + String inputString = request.getParameter("input").toUpperCase(); + + response.setContentType("text/html"); + + PrintWriter out = response.getWriter(); + + out.println(inputString); + } +} From 9f74802e9be763995efaaac28e579c23076de76d Mon Sep 17 00:00:00 2001 From: clininger Date: Sat, 5 Jan 2019 22:02:36 +0700 Subject: [PATCH 002/496] BAEL-2565 --- .../com/baeldung/enums/values/Element1.java | 17 ++++ .../com/baeldung/enums/values/Element2.java | 52 ++++++++++ .../com/baeldung/enums/values/Element3.java | 63 ++++++++++++ .../com/baeldung/enums/values/Element4.java | 95 +++++++++++++++++++ .../com/baeldung/enums/values/Labeled.java | 5 + .../enums/values/Element1UnitTest.java | 48 ++++++++++ .../enums/values/Element2UnitTest.java | 59 ++++++++++++ .../enums/values/Element3UnitTest.java | 57 +++++++++++ .../enums/values/Element4UnitTest.java | 79 +++++++++++++++ 9 files changed, 475 insertions(+) create mode 100644 core-java-8/src/main/java/com/baeldung/enums/values/Element1.java create mode 100644 core-java-8/src/main/java/com/baeldung/enums/values/Element2.java create mode 100644 core-java-8/src/main/java/com/baeldung/enums/values/Element3.java create mode 100644 core-java-8/src/main/java/com/baeldung/enums/values/Element4.java create mode 100644 core-java-8/src/main/java/com/baeldung/enums/values/Labeled.java create mode 100644 core-java-8/src/test/java/com/baeldung/enums/values/Element1UnitTest.java create mode 100644 core-java-8/src/test/java/com/baeldung/enums/values/Element2UnitTest.java create mode 100644 core-java-8/src/test/java/com/baeldung/enums/values/Element3UnitTest.java create mode 100644 core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element1.java b/core-java-8/src/main/java/com/baeldung/enums/values/Element1.java new file mode 100644 index 0000000000..6c80adacb1 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/enums/values/Element1.java @@ -0,0 +1,17 @@ +package com.baeldung.enums.values; + +/** + * This is a simple enum of periodic table elements + */ +public enum Element1 { + H, + HE, + LI, + BE, + B, + C, + N, + O, + F, + NE +} diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element2.java b/core-java-8/src/main/java/com/baeldung/enums/values/Element2.java new file mode 100644 index 0000000000..28bf3a475a --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/enums/values/Element2.java @@ -0,0 +1,52 @@ +package com.baeldung.enums.values; + +/** + * The simple enum has been enhanced to add the name of the element. + */ +public enum Element2 { + H("Hydrogen"), + HE("Helium"), + LI("Lithium"), + BE("Beryllium"), + B("Boron"), + C("Carbon"), + N("Nitrogen"), + O("Oxygen"), + F("Flourine"), + NE("Neon"); + + /** a final variable to store the label, which can't be changed */ + public final String label; + + /** + * A private constructor that sets the label. + * @param label + */ + private Element2(String label) { + this.label = label; + } + + /** + * Look up Element2 instances by the label field. This implementation iterates through + * the values() list to find the label. + * @param label The label to look up + * @return The Element2 instance with the label, or null if not found. + */ + public static Element2 valueOfLabel(String label) { + for (Element2 e2 : values()) { + if (e2.label.equals(label)) { + return e2; + } + } + return null; + } + + /** + * Override the toString() method to return the label instead of the declared name. + * @return + */ + @Override + public String toString() { + return this.label; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element3.java b/core-java-8/src/main/java/com/baeldung/enums/values/Element3.java new file mode 100644 index 0000000000..cb98695de8 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/enums/values/Element3.java @@ -0,0 +1,63 @@ +package com.baeldung.enums.values; + +import java.util.HashMap; +import java.util.Map; + +/** + * A Map has been added to cache labels for faster lookup. + */ +public enum Element3 { + H("Hydrogen"), + HE("Helium"), + LI("Lithium"), + BE("Beryllium"), + B("Boron"), + C("Carbon"), + N("Nitrogen"), + O("Oxygen"), + F("Flourine"), + NE("Neon"); + + /** + * A map to cache labels and their associated Element3 instances. + * Note that this only works if the labels are all unique! + */ + private static final Map BY_LABEL = new HashMap<>(); + + /** populate the BY_LABEL cache */ + static { + for (Element3 e3 : values()) { + BY_LABEL.put(e3.label, e3); + } + } + + /** a final variable to store the label, which can't be changed */ + public final String label; + + /** + * A private constructor that sets the label. + * @param label + */ + private Element3(String label) { + this.label = label; + } + + /** + * Look up Element2 instances by the label field. This implementation finds the + * label in the BY_LABEL cache. + * @param label The label to look up + * @return The Element3 instance with the label, or null if not found. + */ + public static Element3 valueOfLabel(String label) { + return BY_LABEL.get(label); + } + + /** + * Override the toString() method to return the label instead of the declared name. + * @return + */ + @Override + public String toString() { + return this.label; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element4.java b/core-java-8/src/main/java/com/baeldung/enums/values/Element4.java new file mode 100644 index 0000000000..89c45f9d1b --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/enums/values/Element4.java @@ -0,0 +1,95 @@ +package com.baeldung.enums.values; + +import java.util.HashMap; +import java.util.Map; + +/** + * Multiple fields have been added and the Labeled interface is implemented. + */ +public enum Element4 implements Labeled { + H("Hydrogen", 1, 1.008f), + HE("Helium", 2, 4.0026f), + LI("Lithium", 3, 6.94f), + BE("Beryllium", 4, 9.01722f), + B("Boron", 5, 10.81f), + C("Carbon", 6, 12.011f), + N("Nitrogen", 7, 14.007f), + O("Oxygen", 8, 15.999f), + F("Flourine", 9, 18.998f), + NE("Neon", 10, 20.180f); + /** + * Maps cache labels and their associated Element3 instances. + * Note that this only works if the values are all unique! + */ + private static final Map BY_LABEL = new HashMap<>(); + private static final Map BY_ATOMIC_NUMBER = new HashMap<>(); + private static final Map BY_ATOMIC_WEIGHT = new HashMap<>(); + + /** populate the caches */ + static { + for (Element4 e4 : values()) { + BY_LABEL.put(e4.label, e4); + BY_ATOMIC_NUMBER.put(e4.atomicNumber, e4); + BY_ATOMIC_WEIGHT.put(e4.atomicWeight, e4); + } + } + + /** final variables to store the values, which can't be changed */ + public final String label; + public final int atomicNumber; + public final float atomicWeight; + + private Element4(String label, int atomicNumber, float atomicWeight) { + this.label = label; + this.atomicNumber = atomicNumber; + this.atomicWeight = atomicWeight; + } + + /** + * Implement the Labeled interface. + * @return the label value + */ + @Override + public String label() { + return label; + } + + /** + * Look up Element2 instances by the label field. This implementation finds the + * label in the BY_LABEL cache. + * @param label The label to look up + * @return The Element4 instance with the label, or null if not found. + */ + public static Element4 valueOfLabel(String label) { + return BY_LABEL.get(label); + } + + /** + * Look up Element2 instances by the atomicNumber field. This implementation finds the + * atomicNUmber in the cache. + * @param number The atomicNumber to look up + * @return The Element4 instance with the label, or null if not found. + */ + public static Element4 valueOfAtomicNumber(int number) { + return BY_ATOMIC_NUMBER.get(number); + } + + /** + * Look up Element2 instances by the atomicWeight field. This implementation finds the + * atomic weight in the cache. + * @param weight the atomic weight to look up + * @return The Element4 instance with the label, or null if not found. + */ + public static Element4 valueOfAtomicWeight(float weight) { + return BY_ATOMIC_WEIGHT.get(weight); + } + + /** + * Override the toString() method to return the label instead of the declared name. + * @return + */ + @Override + public String toString() { + return this.label; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Labeled.java b/core-java-8/src/main/java/com/baeldung/enums/values/Labeled.java new file mode 100644 index 0000000000..e41d6525f1 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/enums/values/Labeled.java @@ -0,0 +1,5 @@ +package com.baeldung.enums.values; + +public interface Labeled { + String label(); +} diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element1UnitTest.java b/core-java-8/src/test/java/com/baeldung/enums/values/Element1UnitTest.java new file mode 100644 index 0000000000..ab3e684230 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/enums/values/Element1UnitTest.java @@ -0,0 +1,48 @@ +package com.baeldung.enums.values; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author chris + */ +public class Element1UnitTest { + + public Element1UnitTest() { + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + @Test + public void whenAccessingToString_thenItShouldEqualName() { + for (Element1 e1 : Element1.values()) { + assertEquals(e1.name(), e1.toString()); + } + } + + @Test + public void whenCallingValueOf_thenReturnTheCorrectEnum() { + for (Element1 e1 : Element1.values()) { + assertSame(e1, Element1.valueOf(e1.name())); + } + } +} diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element2UnitTest.java b/core-java-8/src/test/java/com/baeldung/enums/values/Element2UnitTest.java new file mode 100644 index 0000000000..02995a2f41 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/enums/values/Element2UnitTest.java @@ -0,0 +1,59 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.enums.values; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author chris + */ +public class Element2UnitTest { + private static final Logger LOGGER = LoggerFactory.getLogger(Element2UnitTest.class); + + public Element2UnitTest() { + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + @Test + public void whenLocatebyLabel_thenReturnCorrectValue() { + for (Element2 e2 : Element2.values()) { + assertSame(e2, Element2.valueOfLabel(e2.label)); + } + } + + /** + * Test of toString method, of class Element2. + */ + @Test + public void whenCallingToString_thenReturnLabel() { + for (Element2 e2 : Element2.values()) { + assertEquals(e2.label, e2.toString()); + } + } +} diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element3UnitTest.java b/core-java-8/src/test/java/com/baeldung/enums/values/Element3UnitTest.java new file mode 100644 index 0000000000..40c76a97b1 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/enums/values/Element3UnitTest.java @@ -0,0 +1,57 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.enums.values; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author chris + */ +public class Element3UnitTest { + + public Element3UnitTest() { + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + @Test + public void whenLocatebyLabel_thenReturnCorrectValue() { + for (Element3 e3 : Element3.values()) { + assertSame(e3, Element3.valueOfLabel(e3.label)); + } + } + + /** + * Test of toString method, of class Element3. + */ + @Test + public void whenCallingToString_thenReturnLabel() { + for (Element3 e3 : Element3.values()) { + assertEquals(e3.label, e3.toString()); + } + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java b/core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java new file mode 100644 index 0000000000..c99a6d440c --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java @@ -0,0 +1,79 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.enums.values; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * + * @author chris + */ +public class Element4UnitTest { + + public Element4UnitTest() { + } + + @BeforeClass + public static void setUpClass() { + } + + @AfterClass + public static void tearDownClass() { + } + + @Before + public void setUp() { + } + + @After + public void tearDown() { + } + + @Test + public void whenLocatebyLabel_thenReturnCorrectValue() { + for (Element4 e4 : Element4.values()) { + Element4 result = Element4.valueOfLabel(e4.label); + + assertSame(e4, result); + } + } + + @Test + public void whenLocatebyAtmNum_thenReturnCorrectValue() { + for (Element4 e4 : Element4.values()) { + Element4 result = Element4.valueOfAtomicNumber(e4.atomicNumber); + + assertSame(e4, result); + } + } + + @Test + public void whenLocatebyAtmWt_thenReturnCorrectValue() { + for (Element4 e4 : Element4.values()) { + Element4 result = Element4.valueOfAtomicWeight(e4.atomicWeight); + + assertSame(e4, result); + } + } + + /** + * Test of toString method, of class Element4. + */ + @Test + public void whenCallingToString_thenReturnLabel() { + for (Element4 e4 : Element4.values()) { + String result = e4.toString(); + + assertEquals(e4.label, result); + } + } + +} From ab598e0de44db61d536ac1eb5a513cc8112fc5cb Mon Sep 17 00:00:00 2001 From: clininger Date: Sat, 5 Jan 2019 22:13:01 +0700 Subject: [PATCH 003/496] BAEL-2565 Test code consistency --- .../baeldung/enums/values/Element4UnitTest.java | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java b/core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java index c99a6d440c..d349dcef72 100644 --- a/core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java @@ -40,27 +40,21 @@ public class Element4UnitTest { @Test public void whenLocatebyLabel_thenReturnCorrectValue() { for (Element4 e4 : Element4.values()) { - Element4 result = Element4.valueOfLabel(e4.label); - - assertSame(e4, result); + assertSame(e4, Element4.valueOfLabel(e4.label)); } } @Test public void whenLocatebyAtmNum_thenReturnCorrectValue() { for (Element4 e4 : Element4.values()) { - Element4 result = Element4.valueOfAtomicNumber(e4.atomicNumber); - - assertSame(e4, result); + assertSame(e4, Element4.valueOfAtomicNumber(e4.atomicNumber)); } } @Test public void whenLocatebyAtmWt_thenReturnCorrectValue() { for (Element4 e4 : Element4.values()) { - Element4 result = Element4.valueOfAtomicWeight(e4.atomicWeight); - - assertSame(e4, result); + assertSame(e4, Element4.valueOfAtomicWeight(e4.atomicWeight)); } } @@ -70,9 +64,7 @@ public class Element4UnitTest { @Test public void whenCallingToString_thenReturnLabel() { for (Element4 e4 : Element4.values()) { - String result = e4.toString(); - - assertEquals(e4.label, result); + assertEquals(e4.label, e4.toString()); } } From 6948055ecf1c871fa615f0ad67ec13bfb93d2908 Mon Sep 17 00:00:00 2001 From: clininger Date: Tue, 8 Jan 2019 15:48:06 +0700 Subject: [PATCH 004/496] BAEL-2565 Move code to different project --- .../src/main/java/com/baeldung/enums/values/Element1.java | 0 .../src/main/java/com/baeldung/enums/values/Element2.java | 0 .../src/main/java/com/baeldung/enums/values/Element3.java | 0 .../src/main/java/com/baeldung/enums/values/Element4.java | 0 .../src/main/java/com/baeldung/enums/values/Labeled.java | 0 .../src/test/java/com/baeldung/enums/values/Element1UnitTest.java | 0 .../src/test/java/com/baeldung/enums/values/Element2UnitTest.java | 0 .../src/test/java/com/baeldung/enums/values/Element3UnitTest.java | 0 .../src/test/java/com/baeldung/enums/values/Element4UnitTest.java | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Element1.java (100%) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Element2.java (100%) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Element3.java (100%) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Element4.java (100%) rename {core-java-8 => core-java-lang}/src/main/java/com/baeldung/enums/values/Labeled.java (100%) rename {core-java-8 => core-java-lang}/src/test/java/com/baeldung/enums/values/Element1UnitTest.java (100%) rename {core-java-8 => core-java-lang}/src/test/java/com/baeldung/enums/values/Element2UnitTest.java (100%) rename {core-java-8 => core-java-lang}/src/test/java/com/baeldung/enums/values/Element3UnitTest.java (100%) rename {core-java-8 => core-java-lang}/src/test/java/com/baeldung/enums/values/Element4UnitTest.java (100%) diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element1.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Element1.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Element1.java diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element2.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Element2.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Element2.java diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element3.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Element3.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Element3.java diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Element4.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Element4.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Element4.java diff --git a/core-java-8/src/main/java/com/baeldung/enums/values/Labeled.java b/core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java similarity index 100% rename from core-java-8/src/main/java/com/baeldung/enums/values/Labeled.java rename to core-java-lang/src/main/java/com/baeldung/enums/values/Labeled.java diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element1UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/enums/values/Element1UnitTest.java rename to core-java-lang/src/test/java/com/baeldung/enums/values/Element1UnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element2UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/enums/values/Element2UnitTest.java rename to core-java-lang/src/test/java/com/baeldung/enums/values/Element2UnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element3UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/enums/values/Element3UnitTest.java rename to core-java-lang/src/test/java/com/baeldung/enums/values/Element3UnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java b/core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java similarity index 100% rename from core-java-8/src/test/java/com/baeldung/enums/values/Element4UnitTest.java rename to core-java-lang/src/test/java/com/baeldung/enums/values/Element4UnitTest.java From 96d4ae478d9f6f82cd9785ec9f64b5728385acc4 Mon Sep 17 00:00:00 2001 From: mikr Date: Fri, 18 Jan 2019 00:23:08 +0100 Subject: [PATCH 005/496] BAEL-2217 forEach within forEach --- .../kotlin/com/baeldung/forEach/forEach.kt | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt b/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt new file mode 100644 index 0000000000..ef56009c71 --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt @@ -0,0 +1,61 @@ +package com.baeldung.forEach + + +class Country(val name : String, val cities : List) + +class City(val name : String, val streets : List) + +class World { + + private val streetsOfAmsterdam = listOf("Herengracht", "Prinsengracht") + private val streetsOfBerlin = listOf("Unter den Linden","Tiergarten") + private val streetsOfMaastricht = listOf("Grote Gracht", "Vrijthof") + private val countries = listOf( + Country("Netherlands", listOf(City("Maastricht", streetsOfMaastricht), + City("Amsterdam", streetsOfAmsterdam))), + Country("Germany", listOf(City("Berlin", streetsOfBerlin)))) + + fun allCountriesIt() { + countries.forEach { println(it.name) } + } + + fun allCountriesItExplicit() { + countries.forEach { it -> println(it.name) } + } + + //here we cannot refer to 'it' anymore inside the forEach + fun allCountriesExplicit() { + countries.forEach { c -> println(c.name) } + } + + fun allNested() { + countries.forEach { + println(it.name) + it.cities.forEach { + println(" ${it.name}") + it.streets.forEach { println(" $it") } + } + } + } + + fun allTable() { + countries.forEach { c -> + c.cities.forEach { p -> + p.streets.forEach { println("${c.name} ${p.name} $it") } + } + } + } +} + +fun main(args : Array) { + + val world = World() + + world.allCountriesExplicit() + + world.allNested() + + world.allTable() +} + + From f5c4e3af74da4a636e558615a20ba0d366698ad5 Mon Sep 17 00:00:00 2001 From: Venkata Kiran Surapaneni Date: Sun, 20 Jan 2019 00:08:52 -0500 Subject: [PATCH 006/496] BAEL-2339 || ResultSet Demo BAEL-2339 || ResultSet Demo --- .../main/java/com/baeldung/jdbc/Employee.java | 6 +- .../com/baeldung/jdbc/ResultSetLiveTest.java | 325 ++++++++++++++++++ 2 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java diff --git a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java index 749855ca3b..8f3fce0378 100644 --- a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java +++ b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java @@ -47,5 +47,9 @@ public class Employee { public void setPosition(String position) { this.position = position; } - + + @Override + public boolean equals(Object obj) { + return this.getId() == ((Employee) obj).getId(); + } } diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java new file mode 100644 index 0000000000..369d5e9222 --- /dev/null +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java @@ -0,0 +1,325 @@ +package com.baeldung.jdbc; + +import static org.junit.Assert.assertEquals; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ResultSetLiveTest { + + private static final Logger logger = Logger.getLogger(ResultSetLiveTest.class); + + private final Employee expectedEmployee1 = new Employee(1, "John", 1000.0, "Developer"); + + private final Employee updatedEmployee1 = new Employee(1, "John", 1100.0, "Developer"); + + private final Employee expectedEmployee2 = new Employee(2, "Chris", 925.0, "DBA"); + + private final int rowCount = 2; + + private static Connection dbConnection; + + @BeforeClass + public static void setup() throws ClassNotFoundException, SQLException { + Class.forName("com.mysql.cj.jdbc.Driver"); + dbConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB?noAccessToProcedureBodies=true", "user1", "pass"); + String tableSql = "CREATE TABLE IF NOT EXISTS employees (emp_id int PRIMARY KEY AUTO_INCREMENT, name varchar(30), position varchar(30), salary double)"; + try (Statement stmt = dbConnection.createStatement()) { + stmt.execute(tableSql); + try (PreparedStatement pstmt = dbConnection.prepareStatement("INSERT INTO employees(name, position, salary) values ('John', 'Developer', 1000.0)")) { + pstmt.executeUpdate(); + } + } + } + + @Test + public void givenDbConnectionA_whenARetreiveByColumnNames_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } + + assertEquals("Employee information retreived by column names.", expectedEmployee1, employee); + } + + @Test + public void givenDbConnectionB_whenBRetreiveByColumnIds_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + Integer empId = rs.getInt(1); + String name = rs.getString(2); + String position = rs.getString(3); + Double salary = rs.getDouble(4); + employee = new Employee(empId, name, salary, position); + } + } + + assertEquals("Employee information retreived by column ids.", employee, expectedEmployee1); + } + + @Test + public void givenDbConnectionD_whenInsertRow_thenCorrect() throws SQLException { + int rowCount = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.moveToInsertRow(); + rs.updateString("name", "Venkat"); + rs.updateString("position", "DBA"); + rs.updateDouble("salary", 925.0); + rs.insertRow(); + rs.moveToCurrentRow(); + rs.last(); + rowCount = rs.getRow(); + } + + assertEquals("Row Count after inserting a row", rowCount, 2); + } + + private Employee populateResultSet(ResultSet rs) throws SQLException { + Employee employee; + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + return employee; + } + + @Test + public void givenDbConnectionE_whenRowCount_thenCorrect() throws SQLException { + int numOfRows = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.last(); + numOfRows = rs.getRow(); + } + + assertEquals("Num of rows", numOfRows, rowCount); + } + + @Test + public void givenDbConnectionG_whenAbsoluteNavigation_thenCorrect() throws SQLException { + Employee secondEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.absolute(2); + secondEmployee = populateResultSet(rs); + } + + assertEquals("Absolute navigation", secondEmployee, expectedEmployee2); + } + + @Test + public void givenDbConnectionH_whenLastNavigation_thenCorrect() throws SQLException { + Employee secondEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.last(); + secondEmployee = populateResultSet(rs); + } + + assertEquals("Using Last", secondEmployee, expectedEmployee2); + } + + @Test + public void givenDbConnectionI_whenNavigation_thenCorrect() throws SQLException { + Employee firstEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.beforeFirst(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.first(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + while (rs.previous()) { + Employee employee = populateResultSet(rs); + } + rs.afterLast(); + while (rs.previous()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + while (rs.previous()) { + firstEmployee = populateResultSet(rs); + } + } + + assertEquals("Several Navigation Options", firstEmployee, updatedEmployee1); + } + + @Test + public void givenDbConnectionJ_whenClosedCursor_thenCorrect() throws SQLException { + int numOfRows = 0; + dbConnection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT)) { + dbConnection.setAutoCommit(false); + pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Chris',2100.0,'Manager')"); + ResultSet rs = pstmt.executeQuery("select * from employees"); + dbConnection.commit(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + numOfRows = rs.getRow(); + } + + assertEquals("Inserted using close cursor after commit", numOfRows, 3); + } + + @Test + public void givenDbConnectionK_whenUpdate_thenCorrect() throws SQLException { + int numOfRows = 0; + try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT)) { + dbConnection.setAutoCommit(false); + pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Michael',1200.0,'Consultant')"); + ResultSet rs = pstmt.executeQuery("select * from employees"); + dbConnection.commit(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + numOfRows = rs.getRow(); + } + + assertEquals("Inserted using hold cursor after commit", numOfRows, 4); + } + + @Test + public void givenDbConnectionL_whenDelete_thenCorrect() throws SQLException { + int numOfRows = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.absolute(3); + rs.deleteRow(); + rs.last(); + numOfRows = rs.getRow(); + } + + assertEquals("Deleted row", numOfRows, 3); + } + + @Test + public void givenDbConnectionC_whenUpdate_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + rs.updateDouble("salary", 1100.0); + rs.updateRow(); + rs.refreshRow(); + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } + + assertEquals("Employee information updated successfully.", employee, updatedEmployee1); + } + + @Test + public void givenDbConnectionE_whenDBMetaInfo_thenCorrect() throws SQLException { + DatabaseMetaData dbmd = dbConnection.getMetaData(); + boolean supportsTypeForward = dbmd.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY); + boolean supportsTypeScrollSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE); + boolean supportsTypeScrollInSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE); + boolean supportsCloseCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + boolean supportsHoldCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); + boolean concurrency4TypeFwdNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + boolean concurrency4TypeFwdNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollInSensitiveNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollInSensitiveNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + boolean concurrency4TypeScrollSensitiveNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollSensitiveNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); + int rsHoldability = dbmd.getResultSetHoldability(); + + assertEquals("checking scroll sensitivity and concur updates : ", concurrency4TypeScrollInSensitiveNConcurUpdatable, true); + } + + @Test + public void givenDbConnectionF_whenRSMetaInfo_thenCorrect() throws SQLException { + int columnCount = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + ResultSetMetaData metaData = rs.getMetaData(); + columnCount = metaData.getColumnCount(); + for (int i = 1; i <= columnCount; i++) { + String catalogName = metaData.getCatalogName(i); + String className = metaData.getColumnClassName(i); + String label = metaData.getColumnLabel(i); + String name = metaData.getColumnName(i); + String typeName = metaData.getColumnTypeName(i); + Integer type = metaData.getColumnType(i); + String tableName = metaData.getTableName(i); + String schemaName = metaData.getSchemaName(i); + boolean isAutoIncrement = metaData.isAutoIncrement(i); + boolean isCaseSensitive = metaData.isCaseSensitive(i); + boolean isCurrency = metaData.isCurrency(i); + boolean isDefiniteWritable = metaData.isDefinitelyWritable(i); + boolean isReadOnly = metaData.isReadOnly(i); + boolean isSearchable = metaData.isSearchable(i); + boolean isReadable = metaData.isReadOnly(i); + boolean isSigned = metaData.isSigned(i); + boolean isWritable = metaData.isWritable(i); + int nullable = metaData.isNullable(i); + } + } + + assertEquals("column count", columnCount, 4); + } + + @Test + public void givenDbConnectionM_whenDelete_thenCorrect() throws SQLException { + PreparedStatement pstmt = null; + ResultSet rs = null; + List listOfEmployees = new ArrayList(); + try { + pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + pstmt.setFetchSize(2); + rs = pstmt.executeQuery(); + rs.setFetchSize(1); + while (rs.next()) { + Employee employee = populateResultSet(rs); + listOfEmployees.add(employee); + } + } catch (Exception e) { + throw e; + } finally { + if (rs != null) + rs.close(); + if (pstmt != null) + pstmt.close(); + } + + assertEquals(listOfEmployees.size(), 3); + } + + @AfterClass + public static void closeConnection() throws SQLException { + PreparedStatement deleteStmt = dbConnection.prepareStatement("drop table employees", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); + deleteStmt.execute(); + dbConnection.close(); + } +} From 2ea39c5110bb0c5201e99eb81a16d7e3283449d3 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 21 Jan 2019 15:48:23 +0400 Subject: [PATCH 007/496] sort array performance --- .../performance/ArraySortBenchmark.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java new file mode 100644 index 0000000000..d7b31d2aa5 --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java @@ -0,0 +1,56 @@ +package com.baeldung.performance; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Measurement(batchSize = 100000, iterations = 10) +@Warmup(batchSize = 100000, iterations = 10) +public class ArraySortBenchmark { + + @State(Scope.Thread) + public static class Initialize { + + String[] array = new String[]{"A", "AB", "B"}; + + List list = new ArrayList<>(); + + @Setup(Level.Trial) + public void setUp() { + list.add("A"); + list.add("AB"); + list.add("B"); + } + + } + + @Benchmark + public String[] benchmarkArraysSort(ArraySortBenchmark.Initialize state) { + Arrays.sort(state.array); + return state.array; + } + + @Benchmark + public List benchmarkCollectionsSort(ArraySortBenchmark.Initialize state) { + Collections.sort(state.list); + return state.list; + } + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(ArraySortBenchmark.class.getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } +} From eb8f0cf66c5464eb6664731477305d9ea16ffd81 Mon Sep 17 00:00:00 2001 From: Venkata Kiran Surapaneni Date: Tue, 22 Jan 2019 02:20:08 -0500 Subject: [PATCH 008/496] Fixed unit tests and equals method for ResultSetLiveTest --- .../main/java/com/baeldung/jdbc/Employee.java | 98 ++-- .../com/baeldung/jdbc/ResultSetLiveTest.java | 551 +++++++++--------- 2 files changed, 344 insertions(+), 305 deletions(-) diff --git a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java index 8f3fce0378..88af4902b5 100644 --- a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java +++ b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java @@ -1,55 +1,71 @@ package com.baeldung.jdbc; +import java.util.Objects; + public class Employee { - private int id; - private String name; - private String position; - private double salary; + private int id; + private String name; + private String position; + private double salary; - public Employee() { - } + public Employee() { + } - public Employee(int id, String name, double salary, String position) { - this.id = id; - this.name = name; - this.salary = salary; - this.position = position; - } + public Employee(int id, String name, double salary, String position) { + this.id = id; + this.name = name; + this.salary = salary; + this.position = position; + } - public int getId() { - return id; - } + public int getId() { + return id; + } - public void setId(int id) { - this.id = id; - } + public void setId(int id) { + this.id = id; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public double getSalary() { - return salary; - } + public double getSalary() { + return salary; + } - public void setSalary(double salary) { - this.salary = salary; - } + public void setSalary(double salary) { + this.salary = salary; + } - public String getPosition() { - return position; - } + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + @Override + public int hashCode() { + return Objects.hash(id, name, position, salary); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Employee other = (Employee) obj; + return id == other.id && Objects.equals(name, other.name) && Objects.equals(position, other.position) + && Double.doubleToLongBits(salary) == Double.doubleToLongBits(other.salary); + } - public void setPosition(String position) { - this.position = position; - } - - @Override - public boolean equals(Object obj) { - return this.getId() == ((Employee) obj).getId(); - } } diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java index 369d5e9222..553c7f9919 100644 --- a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java @@ -23,303 +23,326 @@ import org.junit.runners.MethodSorters; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ResultSetLiveTest { - private static final Logger logger = Logger.getLogger(ResultSetLiveTest.class); + private static final Logger logger = Logger.getLogger(ResultSetLiveTest.class); - private final Employee expectedEmployee1 = new Employee(1, "John", 1000.0, "Developer"); + private final Employee expectedEmployee1 = new Employee(1, "John", 1000.0, "Developer"); - private final Employee updatedEmployee1 = new Employee(1, "John", 1100.0, "Developer"); + private final Employee updatedEmployee1 = new Employee(1, "John", 1100.0, "Developer"); - private final Employee expectedEmployee2 = new Employee(2, "Chris", 925.0, "DBA"); + private final Employee expectedEmployee2 = new Employee(2, "Chris", 925.0, "DBA"); - private final int rowCount = 2; + private final int rowCount = 2; - private static Connection dbConnection; + private static Connection dbConnection; - @BeforeClass - public static void setup() throws ClassNotFoundException, SQLException { - Class.forName("com.mysql.cj.jdbc.Driver"); - dbConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB?noAccessToProcedureBodies=true", "user1", "pass"); - String tableSql = "CREATE TABLE IF NOT EXISTS employees (emp_id int PRIMARY KEY AUTO_INCREMENT, name varchar(30), position varchar(30), salary double)"; - try (Statement stmt = dbConnection.createStatement()) { - stmt.execute(tableSql); - try (PreparedStatement pstmt = dbConnection.prepareStatement("INSERT INTO employees(name, position, salary) values ('John', 'Developer', 1000.0)")) { - pstmt.executeUpdate(); - } - } - } + @BeforeClass + public static void setup() throws ClassNotFoundException, SQLException { + Class.forName("com.mysql.cj.jdbc.Driver"); + dbConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB?noAccessToProcedureBodies=true", + "user1", "pass"); + String tableSql = "CREATE TABLE IF NOT EXISTS employees (emp_id int PRIMARY KEY AUTO_INCREMENT, name varchar(30), position varchar(30), salary double)"; + try (Statement stmt = dbConnection.createStatement()) { + stmt.execute(tableSql); + try (PreparedStatement pstmt = dbConnection.prepareStatement( + "INSERT INTO employees(name, position, salary) values ('John', 'Developer', 1000.0)")) { + pstmt.executeUpdate(); + } + } + } - @Test - public void givenDbConnectionA_whenARetreiveByColumnNames_thenCorrect() throws SQLException { - Employee employee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - String name = rs.getString("name"); - Integer empId = rs.getInt("emp_id"); - Double salary = rs.getDouble("salary"); - String position = rs.getString("position"); - employee = new Employee(empId, name, salary, position); - } - } + @Test + public void givenDbConnectionA_whenARetreiveByColumnNames_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); + ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } - assertEquals("Employee information retreived by column names.", expectedEmployee1, employee); - } + assertEquals("Employee information retreived by column names.", expectedEmployee1, employee); + } - @Test - public void givenDbConnectionB_whenBRetreiveByColumnIds_thenCorrect() throws SQLException { - Employee employee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - Integer empId = rs.getInt(1); - String name = rs.getString(2); - String position = rs.getString(3); - Double salary = rs.getDouble(4); - employee = new Employee(empId, name, salary, position); - } - } + @Test + public void givenDbConnectionB_whenBRetreiveByColumnIds_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); + ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + Integer empId = rs.getInt(1); + String name = rs.getString(2); + String position = rs.getString(3); + Double salary = rs.getDouble(4); + employee = new Employee(empId, name, salary, position); + } + } - assertEquals("Employee information retreived by column ids.", employee, expectedEmployee1); - } + assertEquals("Employee information retreived by column ids.", expectedEmployee1, employee); + } - @Test - public void givenDbConnectionD_whenInsertRow_thenCorrect() throws SQLException { - int rowCount = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.moveToInsertRow(); - rs.updateString("name", "Venkat"); - rs.updateString("position", "DBA"); - rs.updateDouble("salary", 925.0); - rs.insertRow(); - rs.moveToCurrentRow(); - rs.last(); - rowCount = rs.getRow(); - } + @Test + public void givenDbConnectionD_whenInsertRow_thenCorrect() throws SQLException { + int rowCount = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.moveToInsertRow(); + rs.updateString("name", "Venkat"); + rs.updateString("position", "DBA"); + rs.updateDouble("salary", 925.0); + rs.insertRow(); + rs.moveToCurrentRow(); + rs.last(); + rowCount = rs.getRow(); + } - assertEquals("Row Count after inserting a row", rowCount, 2); - } + assertEquals("Row Count after inserting a row", 2, rowCount); + } - private Employee populateResultSet(ResultSet rs) throws SQLException { - Employee employee; - String name = rs.getString("name"); - Integer empId = rs.getInt("emp_id"); - Double salary = rs.getDouble("salary"); - String position = rs.getString("position"); - employee = new Employee(empId, name, salary, position); - return employee; - } + private Employee populateResultSet(ResultSet rs) throws SQLException { + Employee employee; + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + return employee; + } - @Test - public void givenDbConnectionE_whenRowCount_thenCorrect() throws SQLException { - int numOfRows = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.last(); - numOfRows = rs.getRow(); - } + @Test + public void givenDbConnectionE_whenRowCount_thenCorrect() throws SQLException { + int numOfRows = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.last(); + numOfRows = rs.getRow(); + } - assertEquals("Num of rows", numOfRows, rowCount); - } + assertEquals("Num of rows", rowCount, numOfRows); + } - @Test - public void givenDbConnectionG_whenAbsoluteNavigation_thenCorrect() throws SQLException { - Employee secondEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.absolute(2); - secondEmployee = populateResultSet(rs); - } + @Test + public void givenDbConnectionG_whenAbsoluteNavigation_thenCorrect() throws SQLException { + Employee secondEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.absolute(2); + secondEmployee = populateResultSet(rs); + } - assertEquals("Absolute navigation", secondEmployee, expectedEmployee2); - } + assertEquals("Absolute navigation", expectedEmployee2, secondEmployee); + } - @Test - public void givenDbConnectionH_whenLastNavigation_thenCorrect() throws SQLException { - Employee secondEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.last(); - secondEmployee = populateResultSet(rs); - } + @Test + public void givenDbConnectionH_whenLastNavigation_thenCorrect() throws SQLException { + Employee secondEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.last(); + secondEmployee = populateResultSet(rs); + } - assertEquals("Using Last", secondEmployee, expectedEmployee2); - } + assertEquals("Using Last", expectedEmployee2, secondEmployee); + } - @Test - public void givenDbConnectionI_whenNavigation_thenCorrect() throws SQLException { - Employee firstEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - rs.beforeFirst(); - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - rs.first(); - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - while (rs.previous()) { - Employee employee = populateResultSet(rs); - } - rs.afterLast(); - while (rs.previous()) { - Employee employee = populateResultSet(rs); - } - rs.last(); - while (rs.previous()) { - firstEmployee = populateResultSet(rs); - } - } + @Test + public void givenDbConnectionI_whenNavigation_thenCorrect() throws SQLException { + Employee firstEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.beforeFirst(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.first(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + while (rs.previous()) { + Employee employee = populateResultSet(rs); + } + rs.afterLast(); + while (rs.previous()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + while (rs.previous()) { + firstEmployee = populateResultSet(rs); + } + } - assertEquals("Several Navigation Options", firstEmployee, updatedEmployee1); - } + assertEquals("Several Navigation Options", updatedEmployee1, firstEmployee); + } - @Test - public void givenDbConnectionJ_whenClosedCursor_thenCorrect() throws SQLException { - int numOfRows = 0; - dbConnection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); - try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT)) { - dbConnection.setAutoCommit(false); - pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Chris',2100.0,'Manager')"); - ResultSet rs = pstmt.executeQuery("select * from employees"); - dbConnection.commit(); - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - rs.last(); - numOfRows = rs.getRow(); - } + @Test + public void givenDbConnectionJ_whenClosedCursor_thenCorrect() throws SQLException { + int numOfRows = 0; + dbConnection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, + ResultSet.CLOSE_CURSORS_AT_COMMIT)) { + dbConnection.setAutoCommit(false); + pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Chris',2100.0,'Manager')"); + ResultSet rs = pstmt.executeQuery("select * from employees"); + dbConnection.commit(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + numOfRows = rs.getRow(); + } - assertEquals("Inserted using close cursor after commit", numOfRows, 3); - } + assertEquals("Inserted using close cursor after commit", 3, numOfRows); + } - @Test - public void givenDbConnectionK_whenUpdate_thenCorrect() throws SQLException { - int numOfRows = 0; - try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT)) { - dbConnection.setAutoCommit(false); - pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Michael',1200.0,'Consultant')"); - ResultSet rs = pstmt.executeQuery("select * from employees"); - dbConnection.commit(); - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - rs.last(); - numOfRows = rs.getRow(); - } + @Test + public void givenDbConnectionK_whenUpdate_thenCorrect() throws SQLException { + int numOfRows = 0; + try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, + ResultSet.HOLD_CURSORS_OVER_COMMIT)) { + dbConnection.setAutoCommit(false); + pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Michael',1200.0,'Consultant')"); + ResultSet rs = pstmt.executeQuery("select * from employees"); + dbConnection.commit(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + numOfRows = rs.getRow(); + } - assertEquals("Inserted using hold cursor after commit", numOfRows, 4); - } + assertEquals("Inserted using hold cursor after commit", 4, numOfRows); + } - @Test - public void givenDbConnectionL_whenDelete_thenCorrect() throws SQLException { - int numOfRows = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.absolute(3); - rs.deleteRow(); - rs.last(); - numOfRows = rs.getRow(); - } + @Test + public void givenDbConnectionL_whenDelete_thenCorrect() throws SQLException { + int numOfRows = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.absolute(3); + rs.deleteRow(); + rs.last(); + numOfRows = rs.getRow(); + } - assertEquals("Deleted row", numOfRows, 3); - } + assertEquals("Deleted row", 3, numOfRows); + } - @Test - public void givenDbConnectionC_whenUpdate_thenCorrect() throws SQLException { - Employee employee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - rs.updateDouble("salary", 1100.0); - rs.updateRow(); - rs.refreshRow(); - String name = rs.getString("name"); - Integer empId = rs.getInt("emp_id"); - Double salary = rs.getDouble("salary"); - String position = rs.getString("position"); - employee = new Employee(empId, name, salary, position); - } - } + @Test + public void givenDbConnectionC_whenUpdate_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + rs.updateDouble("salary", 1100.0); + rs.updateRow(); + rs.refreshRow(); + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } - assertEquals("Employee information updated successfully.", employee, updatedEmployee1); - } + assertEquals("Employee information updated successfully.", updatedEmployee1, employee); + } - @Test - public void givenDbConnectionE_whenDBMetaInfo_thenCorrect() throws SQLException { - DatabaseMetaData dbmd = dbConnection.getMetaData(); - boolean supportsTypeForward = dbmd.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY); - boolean supportsTypeScrollSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE); - boolean supportsTypeScrollInSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE); - boolean supportsCloseCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); - boolean supportsHoldCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); - boolean concurrency4TypeFwdNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - boolean concurrency4TypeFwdNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); - boolean concurrency4TypeScrollInSensitiveNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); - boolean concurrency4TypeScrollInSensitiveNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - boolean concurrency4TypeScrollSensitiveNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - boolean concurrency4TypeScrollSensitiveNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); - int rsHoldability = dbmd.getResultSetHoldability(); + @Test + public void givenDbConnectionE_whenDBMetaInfo_thenCorrect() throws SQLException { + DatabaseMetaData dbmd = dbConnection.getMetaData(); + boolean supportsTypeForward = dbmd.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY); + boolean supportsTypeScrollSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE); + boolean supportsTypeScrollInSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE); + boolean supportsCloseCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + boolean supportsHoldCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); + boolean concurrency4TypeFwdNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY); + boolean concurrency4TypeFwdNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollInSensitiveNConcurUpdatable = dbmd + .supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollInSensitiveNConcurReadOnly = dbmd + .supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + boolean concurrency4TypeScrollSensitiveNConcurUpdatable = dbmd + .supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollSensitiveNConcurReadOnly = dbmd + .supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); + int rsHoldability = dbmd.getResultSetHoldability(); - assertEquals("checking scroll sensitivity and concur updates : ", concurrency4TypeScrollInSensitiveNConcurUpdatable, true); - } + assertEquals("checking scroll sensitivity and concur updates : ", true, + concurrency4TypeScrollInSensitiveNConcurUpdatable); + } - @Test - public void givenDbConnectionF_whenRSMetaInfo_thenCorrect() throws SQLException { - int columnCount = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - ResultSetMetaData metaData = rs.getMetaData(); - columnCount = metaData.getColumnCount(); - for (int i = 1; i <= columnCount; i++) { - String catalogName = metaData.getCatalogName(i); - String className = metaData.getColumnClassName(i); - String label = metaData.getColumnLabel(i); - String name = metaData.getColumnName(i); - String typeName = metaData.getColumnTypeName(i); - Integer type = metaData.getColumnType(i); - String tableName = metaData.getTableName(i); - String schemaName = metaData.getSchemaName(i); - boolean isAutoIncrement = metaData.isAutoIncrement(i); - boolean isCaseSensitive = metaData.isCaseSensitive(i); - boolean isCurrency = metaData.isCurrency(i); - boolean isDefiniteWritable = metaData.isDefinitelyWritable(i); - boolean isReadOnly = metaData.isReadOnly(i); - boolean isSearchable = metaData.isSearchable(i); - boolean isReadable = metaData.isReadOnly(i); - boolean isSigned = metaData.isSigned(i); - boolean isWritable = metaData.isWritable(i); - int nullable = metaData.isNullable(i); - } - } + @Test + public void givenDbConnectionF_whenRSMetaInfo_thenCorrect() throws SQLException { + int columnCount = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", + ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + ResultSetMetaData metaData = rs.getMetaData(); + columnCount = metaData.getColumnCount(); + for (int i = 1; i <= columnCount; i++) { + String catalogName = metaData.getCatalogName(i); + String className = metaData.getColumnClassName(i); + String label = metaData.getColumnLabel(i); + String name = metaData.getColumnName(i); + String typeName = metaData.getColumnTypeName(i); + Integer type = metaData.getColumnType(i); + String tableName = metaData.getTableName(i); + String schemaName = metaData.getSchemaName(i); + boolean isAutoIncrement = metaData.isAutoIncrement(i); + boolean isCaseSensitive = metaData.isCaseSensitive(i); + boolean isCurrency = metaData.isCurrency(i); + boolean isDefiniteWritable = metaData.isDefinitelyWritable(i); + boolean isReadOnly = metaData.isReadOnly(i); + boolean isSearchable = metaData.isSearchable(i); + boolean isReadable = metaData.isReadOnly(i); + boolean isSigned = metaData.isSigned(i); + boolean isWritable = metaData.isWritable(i); + int nullable = metaData.isNullable(i); + } + } - assertEquals("column count", columnCount, 4); - } + assertEquals("column count", 4, columnCount); + } - @Test - public void givenDbConnectionM_whenDelete_thenCorrect() throws SQLException { - PreparedStatement pstmt = null; - ResultSet rs = null; - List listOfEmployees = new ArrayList(); - try { - pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - pstmt.setFetchSize(2); - rs = pstmt.executeQuery(); - rs.setFetchSize(1); - while (rs.next()) { - Employee employee = populateResultSet(rs); - listOfEmployees.add(employee); - } - } catch (Exception e) { - throw e; - } finally { - if (rs != null) - rs.close(); - if (pstmt != null) - pstmt.close(); - } - - assertEquals(listOfEmployees.size(), 3); - } + @Test + public void givenDbConnectionM_whenDelete_thenCorrect() throws SQLException { + PreparedStatement pstmt = null; + ResultSet rs = null; + List listOfEmployees = new ArrayList(); + try { + pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CONCUR_READ_ONLY); + pstmt.setFetchSize(2); + rs = pstmt.executeQuery(); + rs.setFetchSize(1); + while (rs.next()) { + Employee employee = populateResultSet(rs); + listOfEmployees.add(employee); + } + } catch (Exception e) { + throw e; + } finally { + if (rs != null) + rs.close(); + if (pstmt != null) + pstmt.close(); + } - @AfterClass - public static void closeConnection() throws SQLException { - PreparedStatement deleteStmt = dbConnection.prepareStatement("drop table employees", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); - deleteStmt.execute(); - dbConnection.close(); - } + assertEquals(3, listOfEmployees.size()); + } + + @AfterClass + public static void closeConnection() throws SQLException { + PreparedStatement deleteStmt = dbConnection.prepareStatement("drop table employees", + ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); + deleteStmt.execute(); + dbConnection.close(); + } } From d8da2ef88376de0036e98455ad29830cf8fed653 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Wed, 23 Jan 2019 12:09:26 +0400 Subject: [PATCH 009/496] sorting algorithms benchmarks --- .../performance/ArraySortBenchmark.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java index d7b31d2aa5..371146122c 100644 --- a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java +++ b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java @@ -11,8 +11,8 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MINUTES) @Measurement(batchSize = 100000, iterations = 10) @Warmup(batchSize = 100000, iterations = 10) public class ArraySortBenchmark { @@ -20,27 +20,31 @@ public class ArraySortBenchmark { @State(Scope.Thread) public static class Initialize { - String[] array = new String[]{"A", "AB", "B"}; + int iterations = 1000; - List list = new ArrayList<>(); + int[] array = new int[iterations]; + + List list = new ArrayList<>(); @Setup(Level.Trial) public void setUp() { - list.add("A"); - list.add("AB"); - list.add("B"); + + for (int i = 0; i < iterations; i++) { + array[i] = i; + list.add(i); + } } } @Benchmark - public String[] benchmarkArraysSort(ArraySortBenchmark.Initialize state) { + public int[] benchmarkArraysSort(ArraySortBenchmark.Initialize state) { Arrays.sort(state.array); return state.array; } @Benchmark - public List benchmarkCollectionsSort(ArraySortBenchmark.Initialize state) { + public List benchmarkCollectionsSort(ArraySortBenchmark.Initialize state) { Collections.sort(state.list); return state.list; } From 627a493f8f60c1923599ff07ed990896017dc7c9 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Thu, 24 Jan 2019 13:41:34 +0400 Subject: [PATCH 010/496] minor refactor --- .../main/java/com/baeldung/performance/ArraySortBenchmark.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java index 371146122c..5f126fd67d 100644 --- a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java +++ b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java @@ -23,18 +23,15 @@ public class ArraySortBenchmark { int iterations = 1000; int[] array = new int[iterations]; - List list = new ArrayList<>(); @Setup(Level.Trial) public void setUp() { - for (int i = 0; i < iterations; i++) { array[i] = i; list.add(i); } } - } @Benchmark From 48bad8243930c53eb936e1bc37b2126a10302ea2 Mon Sep 17 00:00:00 2001 From: Venkata Kiran Surapaneni Date: Thu, 24 Jan 2019 13:16:56 -0500 Subject: [PATCH 011/496] Fixed issues with adding the 2nd record --- .../com/baeldung/jdbc/ResultSetLiveTest.java | 554 +++++++++--------- 1 file changed, 268 insertions(+), 286 deletions(-) diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java index 553c7f9919..64d64e76f2 100644 --- a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java @@ -20,329 +20,311 @@ import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; +import junit.framework.Assert; + @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ResultSetLiveTest { - private static final Logger logger = Logger.getLogger(ResultSetLiveTest.class); + private static final Logger logger = Logger.getLogger(ResultSetLiveTest.class); - private final Employee expectedEmployee1 = new Employee(1, "John", 1000.0, "Developer"); + private final Employee expectedEmployee1 = new Employee(1, "John", 1000.0, "Developer"); - private final Employee updatedEmployee1 = new Employee(1, "John", 1100.0, "Developer"); + private final Employee updatedEmployee1 = new Employee(1, "John", 1100.0, "Developer"); - private final Employee expectedEmployee2 = new Employee(2, "Chris", 925.0, "DBA"); + private final Employee expectedEmployee2 = new Employee(2, "Chris", 925.0, "DBA"); - private final int rowCount = 2; + private final int rowCount = 2; - private static Connection dbConnection; + private static Connection dbConnection; - @BeforeClass - public static void setup() throws ClassNotFoundException, SQLException { - Class.forName("com.mysql.cj.jdbc.Driver"); - dbConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB?noAccessToProcedureBodies=true", - "user1", "pass"); - String tableSql = "CREATE TABLE IF NOT EXISTS employees (emp_id int PRIMARY KEY AUTO_INCREMENT, name varchar(30), position varchar(30), salary double)"; - try (Statement stmt = dbConnection.createStatement()) { - stmt.execute(tableSql); - try (PreparedStatement pstmt = dbConnection.prepareStatement( - "INSERT INTO employees(name, position, salary) values ('John', 'Developer', 1000.0)")) { - pstmt.executeUpdate(); - } - } - } + @BeforeClass + public static void setup() throws ClassNotFoundException, SQLException { + Class.forName("com.mysql.cj.jdbc.Driver"); + dbConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB?noAccessToProcedureBodies=true", "user1", "pass"); + String tableSql = "CREATE TABLE IF NOT EXISTS employees (emp_id int PRIMARY KEY AUTO_INCREMENT, name varchar(30), position varchar(30), salary double)"; + try (Statement stmt = dbConnection.createStatement()) { + stmt.execute(tableSql); + try (PreparedStatement pstmt = dbConnection.prepareStatement("INSERT INTO employees(name, position, salary) values ('John', 'Developer', 1000.0)")) { + pstmt.executeUpdate(); + } + } + } - @Test - public void givenDbConnectionA_whenARetreiveByColumnNames_thenCorrect() throws SQLException { - Employee employee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); - ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - String name = rs.getString("name"); - Integer empId = rs.getInt("emp_id"); - Double salary = rs.getDouble("salary"); - String position = rs.getString("position"); - employee = new Employee(empId, name, salary, position); - } - } + @Test + public void givenDbConnectionA_whenRetreiveByColumnNames_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } - assertEquals("Employee information retreived by column names.", expectedEmployee1, employee); - } + assertEquals("Employee information retreived by column names.", expectedEmployee1, employee); + } - @Test - public void givenDbConnectionB_whenBRetreiveByColumnIds_thenCorrect() throws SQLException { - Employee employee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); - ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - Integer empId = rs.getInt(1); - String name = rs.getString(2); - String position = rs.getString(3); - Double salary = rs.getDouble(4); - employee = new Employee(empId, name, salary, position); - } - } + @Test + public void givenDbConnectionB_whenRetreiveByColumnIds_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees"); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + Integer empId = rs.getInt(1); + String name = rs.getString(2); + String position = rs.getString(3); + Double salary = rs.getDouble(4); + employee = new Employee(empId, name, salary, position); + } + } - assertEquals("Employee information retreived by column ids.", expectedEmployee1, employee); - } + assertEquals("Employee information retreived by column ids.", expectedEmployee1, employee); + } - @Test - public void givenDbConnectionD_whenInsertRow_thenCorrect() throws SQLException { - int rowCount = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", - ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.moveToInsertRow(); - rs.updateString("name", "Venkat"); - rs.updateString("position", "DBA"); - rs.updateDouble("salary", 925.0); - rs.insertRow(); - rs.moveToCurrentRow(); - rs.last(); - rowCount = rs.getRow(); - } + @Test + public void givenDbConnectionD_whenInsertRow_thenCorrect() throws SQLException { + int rowCount = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.moveToInsertRow(); + rs.updateString("name", "Chris"); + rs.updateString("position", "DBA"); + rs.updateDouble("salary", 925.0); + rs.insertRow(); + rs.moveToCurrentRow(); + rs.last(); + rowCount = rs.getRow(); + } - assertEquals("Row Count after inserting a row", 2, rowCount); - } + assertEquals("Row Count after inserting a row", 2, rowCount); + } - private Employee populateResultSet(ResultSet rs) throws SQLException { - Employee employee; - String name = rs.getString("name"); - Integer empId = rs.getInt("emp_id"); - Double salary = rs.getDouble("salary"); - String position = rs.getString("position"); - employee = new Employee(empId, name, salary, position); - return employee; - } + private Employee populateResultSet(ResultSet rs) throws SQLException { + Employee employee; + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + return employee; + } - @Test - public void givenDbConnectionE_whenRowCount_thenCorrect() throws SQLException { - int numOfRows = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", - ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.last(); - numOfRows = rs.getRow(); - } + @Test + public void givenDbConnectionE_whenRowCount_thenCorrect() throws SQLException { + int numOfRows = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.last(); + numOfRows = rs.getRow(); + } - assertEquals("Num of rows", rowCount, numOfRows); - } + assertEquals("Num of rows", rowCount, numOfRows); + } - @Test - public void givenDbConnectionG_whenAbsoluteNavigation_thenCorrect() throws SQLException { - Employee secondEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", - ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.absolute(2); - secondEmployee = populateResultSet(rs); - } + @Test + public void givenDbConnectionG_whenAbsoluteNavigation_thenCorrect() throws SQLException { + Employee secondEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.absolute(2); + secondEmployee = populateResultSet(rs); + } - assertEquals("Absolute navigation", expectedEmployee2, secondEmployee); - } + assertEquals("Absolute navigation", expectedEmployee2, secondEmployee); + } - @Test - public void givenDbConnectionH_whenLastNavigation_thenCorrect() throws SQLException { - Employee secondEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", - ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.last(); - secondEmployee = populateResultSet(rs); - } + @Test + public void givenDbConnectionH_whenLastNavigation_thenCorrect() throws SQLException { + Employee secondEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.last(); + secondEmployee = populateResultSet(rs); + } - assertEquals("Using Last", expectedEmployee2, secondEmployee); - } + assertEquals("Using Last", expectedEmployee2, secondEmployee); + } - @Test - public void givenDbConnectionI_whenNavigation_thenCorrect() throws SQLException { - Employee firstEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", - ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - rs.beforeFirst(); - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - rs.first(); - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - while (rs.previous()) { - Employee employee = populateResultSet(rs); - } - rs.afterLast(); - while (rs.previous()) { - Employee employee = populateResultSet(rs); - } - rs.last(); - while (rs.previous()) { - firstEmployee = populateResultSet(rs); - } - } + @Test + public void givenDbConnectionI_whenNavigation_thenCorrect() throws SQLException { + Employee firstEmployee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.beforeFirst(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.first(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + while (rs.previous()) { + Employee employee = populateResultSet(rs); + } + rs.afterLast(); + while (rs.previous()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + while (rs.previous()) { + firstEmployee = populateResultSet(rs); + } + } - assertEquals("Several Navigation Options", updatedEmployee1, firstEmployee); - } + assertEquals("Several Navigation Options", updatedEmployee1, firstEmployee); + } - @Test - public void givenDbConnectionJ_whenClosedCursor_thenCorrect() throws SQLException { - int numOfRows = 0; - dbConnection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); - try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, - ResultSet.CLOSE_CURSORS_AT_COMMIT)) { - dbConnection.setAutoCommit(false); - pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Chris',2100.0,'Manager')"); - ResultSet rs = pstmt.executeQuery("select * from employees"); - dbConnection.commit(); - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - rs.last(); - numOfRows = rs.getRow(); - } + @Test + public void givenDbConnectionJ_whenClosedCursor_thenCorrect() throws SQLException { + int numOfRows = 0; + dbConnection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT)) { + dbConnection.setAutoCommit(false); + pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Chris',2100.0,'Manager')"); + ResultSet rs = pstmt.executeQuery("select * from employees"); + dbConnection.commit(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + numOfRows = rs.getRow(); + } - assertEquals("Inserted using close cursor after commit", 3, numOfRows); - } + assertEquals("Inserted using close cursor after commit", 3, numOfRows); + } - @Test - public void givenDbConnectionK_whenUpdate_thenCorrect() throws SQLException { - int numOfRows = 0; - try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, - ResultSet.HOLD_CURSORS_OVER_COMMIT)) { - dbConnection.setAutoCommit(false); - pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Michael',1200.0,'Consultant')"); - ResultSet rs = pstmt.executeQuery("select * from employees"); - dbConnection.commit(); - while (rs.next()) { - Employee employee = populateResultSet(rs); - } - rs.last(); - numOfRows = rs.getRow(); - } + @Test + public void givenDbConnectionK_whenUpdate_thenCorrect() throws SQLException { + int numOfRows = 0; + try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT)) { + dbConnection.setAutoCommit(false); + pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Michael',1200.0,'Consultant')"); + ResultSet rs = pstmt.executeQuery("select * from employees"); + dbConnection.commit(); + while (rs.next()) { + Employee employee = populateResultSet(rs); + } + rs.last(); + numOfRows = rs.getRow(); + } - assertEquals("Inserted using hold cursor after commit", 4, numOfRows); - } + assertEquals("Inserted using hold cursor after commit", 4, numOfRows); + } - @Test - public void givenDbConnectionL_whenDelete_thenCorrect() throws SQLException { - int numOfRows = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", - ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.absolute(3); - rs.deleteRow(); - rs.last(); - numOfRows = rs.getRow(); - } + @Test + public void givenDbConnectionL_whenDelete_thenCorrect() throws SQLException { + int numOfRows = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + rs.absolute(3); + rs.deleteRow(); + rs.last(); + numOfRows = rs.getRow(); + } - assertEquals("Deleted row", 3, numOfRows); - } + assertEquals("Deleted row", 3, numOfRows); + } - @Test - public void givenDbConnectionC_whenUpdate_thenCorrect() throws SQLException { - Employee employee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", - ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - while (rs.next()) { - rs.updateDouble("salary", 1100.0); - rs.updateRow(); - rs.refreshRow(); - String name = rs.getString("name"); - Integer empId = rs.getInt("emp_id"); - Double salary = rs.getDouble("salary"); - String position = rs.getString("position"); - employee = new Employee(empId, name, salary, position); - } - } + @Test + public void givenDbConnectionC_whenUpdate_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { - assertEquals("Employee information updated successfully.", updatedEmployee1, employee); - } + Assert.assertEquals(1000.0, rs.getDouble("salary")); - @Test - public void givenDbConnectionE_whenDBMetaInfo_thenCorrect() throws SQLException { - DatabaseMetaData dbmd = dbConnection.getMetaData(); - boolean supportsTypeForward = dbmd.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY); - boolean supportsTypeScrollSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE); - boolean supportsTypeScrollInSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE); - boolean supportsCloseCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); - boolean supportsHoldCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); - boolean concurrency4TypeFwdNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, - ResultSet.CONCUR_READ_ONLY); - boolean concurrency4TypeFwdNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, - ResultSet.CONCUR_UPDATABLE); - boolean concurrency4TypeScrollInSensitiveNConcurUpdatable = dbmd - .supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); - boolean concurrency4TypeScrollInSensitiveNConcurReadOnly = dbmd - .supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); - boolean concurrency4TypeScrollSensitiveNConcurUpdatable = dbmd - .supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - boolean concurrency4TypeScrollSensitiveNConcurReadOnly = dbmd - .supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); - int rsHoldability = dbmd.getResultSetHoldability(); + rs.updateDouble("salary", 1100.0); + rs.updateRow(); - assertEquals("checking scroll sensitivity and concur updates : ", true, - concurrency4TypeScrollInSensitiveNConcurUpdatable); - } + Assert.assertEquals(1100.0, rs.getDouble("salary")); - @Test - public void givenDbConnectionF_whenRSMetaInfo_thenCorrect() throws SQLException { - int columnCount = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", - ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - ResultSetMetaData metaData = rs.getMetaData(); - columnCount = metaData.getColumnCount(); - for (int i = 1; i <= columnCount; i++) { - String catalogName = metaData.getCatalogName(i); - String className = metaData.getColumnClassName(i); - String label = metaData.getColumnLabel(i); - String name = metaData.getColumnName(i); - String typeName = metaData.getColumnTypeName(i); - Integer type = metaData.getColumnType(i); - String tableName = metaData.getTableName(i); - String schemaName = metaData.getSchemaName(i); - boolean isAutoIncrement = metaData.isAutoIncrement(i); - boolean isCaseSensitive = metaData.isCaseSensitive(i); - boolean isCurrency = metaData.isCurrency(i); - boolean isDefiniteWritable = metaData.isDefinitelyWritable(i); - boolean isReadOnly = metaData.isReadOnly(i); - boolean isSearchable = metaData.isSearchable(i); - boolean isReadable = metaData.isReadOnly(i); - boolean isSigned = metaData.isSigned(i); - boolean isWritable = metaData.isWritable(i); - int nullable = metaData.isNullable(i); - } - } + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } + } - assertEquals("column count", 4, columnCount); - } + @Test + public void givenDbConnectionE_whenDBMetaInfo_thenCorrect() throws SQLException { + DatabaseMetaData dbmd = dbConnection.getMetaData(); + boolean supportsTypeForward = dbmd.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY); + boolean supportsTypeScrollSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE); + boolean supportsTypeScrollInSensitive = dbmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE); + boolean supportsCloseCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + boolean supportsHoldCursorsAtCommit = dbmd.supportsResultSetHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); + boolean concurrency4TypeFwdNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + boolean concurrency4TypeFwdNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollInSensitiveNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollInSensitiveNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); + boolean concurrency4TypeScrollSensitiveNConcurUpdatable = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + boolean concurrency4TypeScrollSensitiveNConcurReadOnly = dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); + int rsHoldability = dbmd.getResultSetHoldability(); - @Test - public void givenDbConnectionM_whenDelete_thenCorrect() throws SQLException { - PreparedStatement pstmt = null; - ResultSet rs = null; - List listOfEmployees = new ArrayList(); - try { - pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_FORWARD_ONLY, - ResultSet.CONCUR_READ_ONLY); - pstmt.setFetchSize(2); - rs = pstmt.executeQuery(); - rs.setFetchSize(1); - while (rs.next()) { - Employee employee = populateResultSet(rs); - listOfEmployees.add(employee); - } - } catch (Exception e) { - throw e; - } finally { - if (rs != null) - rs.close(); - if (pstmt != null) - pstmt.close(); - } + assertEquals("checking scroll sensitivity and concur updates : ", true, concurrency4TypeScrollInSensitiveNConcurUpdatable); + } - assertEquals(3, listOfEmployees.size()); - } + @Test + public void givenDbConnectionF_whenRSMetaInfo_thenCorrect() throws SQLException { + int columnCount = 0; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + ResultSetMetaData metaData = rs.getMetaData(); + columnCount = metaData.getColumnCount(); + for (int i = 1; i <= columnCount; i++) { + String catalogName = metaData.getCatalogName(i); + String className = metaData.getColumnClassName(i); + String label = metaData.getColumnLabel(i); + String name = metaData.getColumnName(i); + String typeName = metaData.getColumnTypeName(i); + Integer type = metaData.getColumnType(i); + String tableName = metaData.getTableName(i); + String schemaName = metaData.getSchemaName(i); + boolean isAutoIncrement = metaData.isAutoIncrement(i); + boolean isCaseSensitive = metaData.isCaseSensitive(i); + boolean isCurrency = metaData.isCurrency(i); + boolean isDefiniteWritable = metaData.isDefinitelyWritable(i); + boolean isReadOnly = metaData.isReadOnly(i); + boolean isSearchable = metaData.isSearchable(i); + boolean isReadable = metaData.isReadOnly(i); + boolean isSigned = metaData.isSigned(i); + boolean isWritable = metaData.isWritable(i); + int nullable = metaData.isNullable(i); + } + } - @AfterClass - public static void closeConnection() throws SQLException { - PreparedStatement deleteStmt = dbConnection.prepareStatement("drop table employees", - ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); - deleteStmt.execute(); - dbConnection.close(); - } + assertEquals("column count", 4, columnCount); + } + + @Test + public void givenDbConnectionM_whenDelete_thenCorrect() throws SQLException { + PreparedStatement pstmt = null; + ResultSet rs = null; + List listOfEmployees = new ArrayList(); + try { + pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + pstmt.setFetchSize(2); + rs = pstmt.executeQuery(); + rs.setFetchSize(1); + while (rs.next()) { + Employee employee = populateResultSet(rs); + listOfEmployees.add(employee); + } + } catch (Exception e) { + throw e; + } finally { + if (rs != null) + rs.close(); + if (pstmt != null) + pstmt.close(); + } + + assertEquals(3, listOfEmployees.size()); + } + + @AfterClass + public static void closeConnection() throws SQLException { + PreparedStatement deleteStmt = dbConnection.prepareStatement("drop table employees", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); + deleteStmt.execute(); + dbConnection.close(); + } } From d9b88ed303d95a2d2ed72c34c445f7a9f88181a4 Mon Sep 17 00:00:00 2001 From: Venkata Kiran Surapaneni Date: Thu, 24 Jan 2019 15:03:42 -0500 Subject: [PATCH 012/496] Fixed some resultset creation --- .../src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java index 64d64e76f2..ef01382e2c 100644 --- a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java @@ -112,7 +112,7 @@ public class ResultSetLiveTest { @Test public void givenDbConnectionE_whenRowCount_thenCorrect() throws SQLException { int numOfRows = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE); ResultSet rs = pstmt.executeQuery()) { rs.last(); numOfRows = rs.getRow(); } @@ -123,7 +123,7 @@ public class ResultSetLiveTest { @Test public void givenDbConnectionG_whenAbsoluteNavigation_thenCorrect() throws SQLException { Employee secondEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE); ResultSet rs = pstmt.executeQuery()) { rs.absolute(2); secondEmployee = populateResultSet(rs); } @@ -145,7 +145,7 @@ public class ResultSetLiveTest { @Test public void givenDbConnectionI_whenNavigation_thenCorrect() throws SQLException { Employee firstEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE); ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { Employee employee = populateResultSet(rs); } From 2fadf8b5a0cda9dedf9f9e40e430a825257d9832 Mon Sep 17 00:00:00 2001 From: Venkata Kiran Surapaneni Date: Thu, 24 Jan 2019 15:09:02 -0500 Subject: [PATCH 013/496] d --- .../src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java index ef01382e2c..7f714a9b32 100644 --- a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java @@ -79,7 +79,7 @@ public class ResultSetLiveTest { } } - assertEquals("Employee information retreived by column ids.", expectedEmployee1, employee); + assertEquals("Employee information retreived by column ids:", expectedEmployee1, employee); } @Test From 474a3675f1575b244f15d1a812a94aa4d4ae52f3 Mon Sep 17 00:00:00 2001 From: Venkata Kiran Surapaneni Date: Fri, 25 Jan 2019 03:06:50 -0500 Subject: [PATCH 014/496] Fixed the name of the fetch example --- .../com/baeldung/jdbc/ResultSetLiveTest.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java index 7f714a9b32..2762aeda5e 100644 --- a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java @@ -79,7 +79,7 @@ public class ResultSetLiveTest { } } - assertEquals("Employee information retreived by column ids:", expectedEmployee1, employee); + assertEquals("Employee information retreived by column ids.", expectedEmployee1, employee); } @Test @@ -112,7 +112,7 @@ public class ResultSetLiveTest { @Test public void givenDbConnectionE_whenRowCount_thenCorrect() throws SQLException { int numOfRows = 0; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE); ResultSet rs = pstmt.executeQuery()) { + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { rs.last(); numOfRows = rs.getRow(); } @@ -123,7 +123,7 @@ public class ResultSetLiveTest { @Test public void givenDbConnectionG_whenAbsoluteNavigation_thenCorrect() throws SQLException { Employee secondEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE); ResultSet rs = pstmt.executeQuery()) { + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { rs.absolute(2); secondEmployee = populateResultSet(rs); } @@ -145,7 +145,7 @@ public class ResultSetLiveTest { @Test public void givenDbConnectionI_whenNavigation_thenCorrect() throws SQLException { Employee firstEmployee = null; - try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE); ResultSet rs = pstmt.executeQuery()) { + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { Employee employee = populateResultSet(rs); } @@ -195,6 +195,7 @@ public class ResultSetLiveTest { @Test public void givenDbConnectionK_whenUpdate_thenCorrect() throws SQLException { int numOfRows = 0; + dbConnection.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT)) { dbConnection.setAutoCommit(false); pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Michael',1200.0,'Consultant')"); @@ -211,15 +212,16 @@ public class ResultSetLiveTest { } @Test - public void givenDbConnectionL_whenDelete_thenCorrect() throws SQLException { + public void givenDbConnectionM_whenDelete_thenCorrect() throws SQLException { int numOfRows = 0; try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { rs.absolute(3); rs.deleteRow(); + } + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { rs.last(); numOfRows = rs.getRow(); } - assertEquals("Deleted row", 3, numOfRows); } @@ -296,13 +298,13 @@ public class ResultSetLiveTest { } @Test - public void givenDbConnectionM_whenDelete_thenCorrect() throws SQLException { + public void givenDbConnectionL_whenFetch_thenCorrect() throws SQLException { PreparedStatement pstmt = null; ResultSet rs = null; List listOfEmployees = new ArrayList(); try { - pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - pstmt.setFetchSize(2); + pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); + pstmt.setFetchSize(1); rs = pstmt.executeQuery(); rs.setFetchSize(1); while (rs.next()) { @@ -318,7 +320,7 @@ public class ResultSetLiveTest { pstmt.close(); } - assertEquals(3, listOfEmployees.size()); + assertEquals(4, listOfEmployees.size()); } @AfterClass From 29452abde43333219fce7d4a229e8c152615b1fd Mon Sep 17 00:00:00 2001 From: Erhan KARAKAYA Date: Sun, 27 Jan 2019 03:27:38 +0300 Subject: [PATCH 015/496] Added tutorial sample for BAEL-2550 --- .../AbstractGenericService.java | 38 +++++++++++++ .../sampleabstract/AbstractService.java | 57 +++++++++++++++++++ .../org/baeldung/sampleabstract/BarBean.java | 12 ++++ .../org/baeldung/sampleabstract/DemoApp.java | 32 +++++++++++ .../baeldung/sampleabstract/FooBarBean.java | 12 ++++ .../org/baeldung/sampleabstract/FooBean.java | 12 ++++ .../sampleabstract/FooGenericService.java | 8 +++ .../baeldung/sampleabstract/FooService.java | 14 +++++ 8 files changed, 185 insertions(+) create mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/AbstractGenericService.java create mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/AbstractService.java create mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/BarBean.java create mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java create mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/FooBarBean.java create mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/FooBean.java create mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/FooGenericService.java create mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/FooService.java diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractGenericService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractGenericService.java new file mode 100644 index 0000000000..88451d5181 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractGenericService.java @@ -0,0 +1,38 @@ +package org.baeldung.sampleabstract; + +import org.springframework.beans.factory.annotation.Autowired; + +public abstract class AbstractGenericService { + + @Autowired + private T genericFieldT; + + private S genericFieldS; + + public T getGenericFieldT() { + + return genericFieldT; + } + + public void setGenericFieldT(T genericFieldT) { + + this.genericFieldT = genericFieldT; + } + + public S getGenericFieldS() { + + return genericFieldS; + } + + @Autowired + public void setGenericFieldS(S genericFieldS) { + + this.genericFieldS = genericFieldS; + } + + public void afterInitialize() { + + System.out.println(genericFieldT.getClass().getSimpleName()); + System.out.println(genericFieldS.getClass().getSimpleName()); + } +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractService.java new file mode 100644 index 0000000000..51882f20b3 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractService.java @@ -0,0 +1,57 @@ +package org.baeldung.sampleabstract; + +import org.springframework.beans.factory.annotation.Autowired; + + +public abstract class AbstractService { + + @Autowired + private FooBean fooBean; + + private BarBean barBean; + + private FooBarBean fooBarBean; + + public AbstractService(FooBarBean fooBarBean) { + + this.fooBarBean = fooBarBean; + } + + public FooBean getFooBean() { + + return fooBean; + } + + public void setFooBean(FooBean fooBean) { + + this.fooBean = fooBean; + } + + public BarBean getBarBean() { + + return barBean; + } + + @Autowired + public void setBarBean(BarBean barBean) { + + this.barBean = barBean; + } + + public FooBarBean getFooBarBean() { + + return fooBarBean; + } + + public void setFooBarBean(FooBarBean fooBarBean) { + + this.fooBarBean = fooBarBean; + } + + public void afterInitialize() { + + System.out.println(fooBean.value()); + System.out.println(barBean.value()); + System.out.println(fooBarBean.value()); + } +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/BarBean.java b/spring-all/src/main/java/org/baeldung/sampleabstract/BarBean.java new file mode 100644 index 0000000000..8aeb5d2001 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/BarBean.java @@ -0,0 +1,12 @@ +package org.baeldung.sampleabstract; + +import org.springframework.stereotype.Component; + +@Component +public class BarBean { + + public String value() { + + return "barBean"; + } +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java b/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java new file mode 100644 index 0000000000..f6e7fd47b5 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java @@ -0,0 +1,32 @@ +package org.baeldung.sampleabstract; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; + +@Configuration +@ComponentScan(basePackages = "org.baeldung.sampleabstract") +public class DemoApp { + + @Autowired + private FooService fooService; + + @Autowired + private FooGenericService fooGenericService; + + public static void main(String[] args) { + + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(DemoApp.class); + } + + @PostConstruct + public void afterInitialize() { + + fooService.afterInitialize(); + fooGenericService.afterInitialize(); + } +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/FooBarBean.java b/spring-all/src/main/java/org/baeldung/sampleabstract/FooBarBean.java new file mode 100644 index 0000000000..0f46518a41 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/FooBarBean.java @@ -0,0 +1,12 @@ +package org.baeldung.sampleabstract; + +import org.springframework.stereotype.Component; + +@Component +public class FooBarBean { + + public String value() { + + return "fooBarBean"; + } +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/FooBean.java b/spring-all/src/main/java/org/baeldung/sampleabstract/FooBean.java new file mode 100644 index 0000000000..5ef623b5af --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/FooBean.java @@ -0,0 +1,12 @@ +package org.baeldung.sampleabstract; + +import org.springframework.stereotype.Component; + +@Component +public class FooBean { + + public String value() { + + return "fooBean"; + } +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/FooGenericService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/FooGenericService.java new file mode 100644 index 0000000000..45ad15e33a --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/FooGenericService.java @@ -0,0 +1,8 @@ +package org.baeldung.sampleabstract; + +import org.springframework.stereotype.Component; + +@Component +public class FooGenericService extends AbstractGenericService { + +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/FooService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/FooService.java new file mode 100644 index 0000000000..8bc625e098 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/FooService.java @@ -0,0 +1,14 @@ +package org.baeldung.sampleabstract; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class FooService extends AbstractService { + + @Autowired + public FooService(FooBarBean fooBarBean) { + + super(fooBarBean); + } +} From 435f1982985b316d7f2653997ea7d3ec3a8b2175 Mon Sep 17 00:00:00 2001 From: Venkata Kiran Surapaneni Date: Mon, 28 Jan 2019 01:55:39 -0500 Subject: [PATCH 016/496] applied formatter --- .../main/java/com/baeldung/jdbc/Employee.java | 103 +++++++++--------- 1 file changed, 51 insertions(+), 52 deletions(-) diff --git a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java index 88af4902b5..27aef8b82f 100644 --- a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java +++ b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/Employee.java @@ -3,69 +3,68 @@ package com.baeldung.jdbc; import java.util.Objects; public class Employee { - private int id; - private String name; - private String position; - private double salary; + private int id; + private String name; + private String position; + private double salary; - public Employee() { - } + public Employee() { + } - public Employee(int id, String name, double salary, String position) { - this.id = id; - this.name = name; - this.salary = salary; - this.position = position; - } + public Employee(int id, String name, double salary, String position) { + this.id = id; + this.name = name; + this.salary = salary; + this.position = position; + } - public int getId() { - return id; - } + public int getId() { + return id; + } - public void setId(int id) { - this.id = id; - } + public void setId(int id) { + this.id = id; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public double getSalary() { - return salary; - } + public double getSalary() { + return salary; + } - public void setSalary(double salary) { - this.salary = salary; - } + public void setSalary(double salary) { + this.salary = salary; + } - public String getPosition() { - return position; - } + public String getPosition() { + return position; + } - public void setPosition(String position) { - this.position = position; - } + public void setPosition(String position) { + this.position = position; + } - @Override - public int hashCode() { - return Objects.hash(id, name, position, salary); - } + @Override + public int hashCode() { + return Objects.hash(id, name, position, salary); + } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Employee other = (Employee) obj; - return id == other.id && Objects.equals(name, other.name) && Objects.equals(position, other.position) - && Double.doubleToLongBits(salary) == Double.doubleToLongBits(other.salary); - } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Employee other = (Employee) obj; + return id == other.id && Objects.equals(name, other.name) && Objects.equals(position, other.position) && Double.doubleToLongBits(salary) == Double.doubleToLongBits(other.salary); + } } From 009a99e340aff185da8eeeed16533b9114756595 Mon Sep 17 00:00:00 2001 From: macroscopic64 Date: Sun, 3 Feb 2019 00:33:17 +0530 Subject: [PATCH 017/496] example for multi-release jar --- .../com/baeldung/multireleaseapp/App.java | 11 +++++++++ .../baeldung/multireleaseapp/DateHelper.java | 24 +++++++++++++++++++ .../baeldung/multireleaseapp/DateHelper.java | 13 ++++++++++ 3 files changed, 48 insertions(+) create mode 100644 core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java create mode 100644 core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java create mode 100644 core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java diff --git a/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java b/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java new file mode 100644 index 0000000000..c2e738384a --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java @@ -0,0 +1,11 @@ +package com.baeldung.multireleaseapp; + +public class App { + + public static void main(String[] args) throws Exception { + String dateToCheck = args[0]; + boolean isLeapYear = DateHelper.checkIfLeapYear(dateToCheck); + System.out.println("Date given " + dateToCheck + " is leap year: " + isLeapYear); + } + +} diff --git a/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java b/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java new file mode 100644 index 0000000000..842ac00350 --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java @@ -0,0 +1,24 @@ +package com.baeldung.multireleaseapp; + +import java.text.SimpleDateFormat; +import java.util.Calendar; + +public class DateHelper { + + public static boolean checkIfLeapYear(String dateStr) throws Exception { + System.out.println("Checking for leap year using Java 1 calendar API "); + boolean isLeapYear = false; + Calendar cal = Calendar.getInstance(); + cal.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(dateStr)); + int year = cal.get(Calendar.YEAR); + if (year % 4 == 0) { + if (year % 100 == 0) { + isLeapYear = (year % 400 == 0) ? true : false; + } else { + isLeapYear = true; + } + } + return isLeapYear; + } + +} diff --git a/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java b/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java new file mode 100644 index 0000000000..1d8a10f145 --- /dev/null +++ b/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java @@ -0,0 +1,13 @@ +package com.baeldung.multireleaseapp; + +import java.time.LocalDate; + +public class DateHelper { + + public static boolean checkIfLeapYear(String dateStr) throws Exception { + System.out.println("Checking for leap year using Java 9 Date Api"); + return LocalDate.parse(dateStr) + .isLeapYear(); + } + +} From 11bce96dc8da2da189f8da0df99ffe8fbe28c37f Mon Sep 17 00:00:00 2001 From: Erhan KARAKAYA Date: Sun, 3 Feb 2019 22:47:10 +0300 Subject: [PATCH 018/496] Removed generic examples --- .../AbstractGenericService.java | 38 ------------------- .../org/baeldung/sampleabstract/DemoApp.java | 4 -- .../sampleabstract/FooGenericService.java | 8 ---- 3 files changed, 50 deletions(-) delete mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/AbstractGenericService.java delete mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/FooGenericService.java diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractGenericService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractGenericService.java deleted file mode 100644 index 88451d5181..0000000000 --- a/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractGenericService.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.baeldung.sampleabstract; - -import org.springframework.beans.factory.annotation.Autowired; - -public abstract class AbstractGenericService { - - @Autowired - private T genericFieldT; - - private S genericFieldS; - - public T getGenericFieldT() { - - return genericFieldT; - } - - public void setGenericFieldT(T genericFieldT) { - - this.genericFieldT = genericFieldT; - } - - public S getGenericFieldS() { - - return genericFieldS; - } - - @Autowired - public void setGenericFieldS(S genericFieldS) { - - this.genericFieldS = genericFieldS; - } - - public void afterInitialize() { - - System.out.println(genericFieldT.getClass().getSimpleName()); - System.out.println(genericFieldS.getClass().getSimpleName()); - } -} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java b/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java index f6e7fd47b5..0c3c4ea083 100644 --- a/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java @@ -15,9 +15,6 @@ public class DemoApp { @Autowired private FooService fooService; - @Autowired - private FooGenericService fooGenericService; - public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(DemoApp.class); @@ -27,6 +24,5 @@ public class DemoApp { public void afterInitialize() { fooService.afterInitialize(); - fooGenericService.afterInitialize(); } } diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/FooGenericService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/FooGenericService.java deleted file mode 100644 index 45ad15e33a..0000000000 --- a/spring-all/src/main/java/org/baeldung/sampleabstract/FooGenericService.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.baeldung.sampleabstract; - -import org.springframework.stereotype.Component; - -@Component -public class FooGenericService extends AbstractGenericService { - -} From 04749e33133c30b2bdc0e35251d3dc8026ed4b87 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Tue, 5 Feb 2019 18:41:57 +0100 Subject: [PATCH 019/496] [BAEL-2538] Added tutorial queries and tests --- .../com/baeldung/util/LocalDateConverter.java | 25 +++ .../dao/repositories/user/UserRepository.java | 19 ++ .../user/UserRepositoryCustom.java | 4 + .../user/UserRepositoryCustomImpl.java | 14 ++ .../java/com/baeldung/domain/user/User.java | 46 +++- .../UserRepositoryIntegrationTest.java | 205 +++++++++++++++--- 6 files changed, 277 insertions(+), 36 deletions(-) create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java rename persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/{ => user}/UserRepositoryIntegrationTest.java (59%) diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java new file mode 100644 index 0000000000..00fd378b05 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java @@ -0,0 +1,25 @@ +package com.baeldung.util; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; +import java.sql.Date; +import java.time.LocalDate; +import java.util.Optional; + +@Converter(autoApply = true) +public class LocalDateConverter implements AttributeConverter { + + @Override + public Date convertToDatabaseColumn(LocalDate localDate) { + return Optional.ofNullable(localDate) + .map(Date::valueOf) + .orElse(null); + } + + @Override + public LocalDate convertToEntityAttribute(Date date) { + return Optional.ofNullable(date) + .map(Date::toLocalDate) + .orElse(null); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java index 7f54254832..366a784fe4 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java @@ -10,6 +10,7 @@ import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import java.time.LocalDate; import java.util.Collection; import java.util.List; import java.util.stream.Stream; @@ -18,6 +19,9 @@ public interface UserRepository extends JpaRepository , UserRepos Stream findAllByName(String name); + @Query("select u from User u where u.email like '%@gmail.com'") + List findUsersWithGmailAddress(); + @Query("SELECT u FROM User u WHERE u.status = 1") Collection findAllActiveUsers(); @@ -67,4 +71,19 @@ public interface UserRepository extends JpaRepository , UserRepos @Modifying @Query(value = "UPDATE USERS.Users u SET u.status = ? WHERE u.name = ?", nativeQuery = true) int updateUserSetStatusForNameNative(Integer status, String name); + + void deleteAllByCreationDateAfter(LocalDate date); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query("update User u set u.active = false where u.lastLoginDate < :date") + void deactivateUsersNotLoggedInSince(@Param("date") LocalDate date); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query("delete User u where u.active = false") + void deleteDeactivatedUsers(); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query(value = "alter table USERS.USERS add column deleted int(1) not null default 0", nativeQuery = true) + void addDeletedColumn(); + } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java index 72c1fd5d00..0f29cd656e 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustom.java @@ -1,10 +1,14 @@ package com.baeldung.dao.repositories.user; +import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.function.Predicate; import com.baeldung.domain.user.User; public interface UserRepositoryCustom { List findUserByEmails(Set emails); + + List findAllUsersByPredicates(Collection> predicates); } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java index 9f841caf68..7b2a7ab123 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepositoryCustomImpl.java @@ -1,8 +1,11 @@ package com.baeldung.dao.repositories.user; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @@ -40,4 +43,15 @@ public class UserRepositoryCustomImpl implements UserRepositoryCustom { .getResultList(); } + @Override + public List findAllUsersByPredicates(Collection> predicates) { + List allUsers = entityManager.createQuery("select u from User u", User.class).getResultList(); + Stream allUsersStream = allUsers.stream(); + for (java.util.function.Predicate predicate : predicates) { + allUsersStream = allUsersStream.filter(predicate); + } + + return allUsersStream.collect(Collectors.toList()); + } + } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/user/User.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/user/User.java index 3a8b617d9a..49e36505e4 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/user/User.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/user/User.java @@ -1,7 +1,9 @@ package com.baeldung.domain.user; import javax.persistence.*; +import java.time.LocalDate; import java.util.List; +import java.util.Objects; @Entity @Table(name = "users", schema = "users") @@ -11,6 +13,9 @@ public class User { @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; private String name; + private LocalDate creationDate; + private LocalDate lastLoginDate; + private boolean active; private int age; @Column(unique = true, nullable = false) private String email; @@ -22,10 +27,12 @@ public class User { super(); } - public User(String name, String email, Integer status) { + public User(String name, LocalDate creationDate, String email, Integer status) { this.name = name; + this.creationDate = creationDate; this.email = email; this.status = status; + this.active = true; } public int getId() { @@ -44,6 +51,10 @@ public class User { this.name = name; } + public LocalDate getCreationDate() { + return creationDate; + } + public String getEmail() { return email; } @@ -83,4 +94,37 @@ public class User { return builder.toString(); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return id == user.id && + age == user.age && + Objects.equals(name, user.name) && + Objects.equals(creationDate, user.creationDate) && + Objects.equals(email, user.email) && + Objects.equals(status, user.status); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, creationDate, age, email, status); + } + + public LocalDate getLastLoginDate() { + return lastLoginDate; + } + + public void setLastLoginDate(LocalDate lastLoginDate) { + this.lastLoginDate = lastLoginDate; + } + + public boolean isActive() { + return active; + } + + public void setActive(boolean active) { + this.active = active; + } } \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/user/UserRepositoryIntegrationTest.java similarity index 59% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/user/UserRepositoryIntegrationTest.java index b05086d00e..d57b5d16d0 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/user/UserRepositoryIntegrationTest.java @@ -1,12 +1,12 @@ -package com.baeldung.dao.repositories; +package com.baeldung.dao.repositories.user; import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.dao.repositories.user.UserRepository; import com.baeldung.domain.user.User; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -17,13 +17,15 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import javax.persistence.EntityManager; +import javax.persistence.Query; +import java.time.LocalDate; +import java.util.*; +import java.util.function.Predicate; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.*; /** * Created by adam. @@ -48,6 +50,8 @@ public class UserRepositoryIntegrationTest { @Autowired private UserRepository userRepository; + @Autowired + private EntityManager entityManager; @Test @Transactional @@ -270,9 +274,9 @@ public class UserRepositoryIntegrationTest { @Test public void givenUsersInDBWhenFindAllWithSortByNameThenReturnUsersSorted() { - userRepository.save(new User(USER_NAME_ADAM, USER_EMAIL, ACTIVE_STATUS)); - userRepository.save(new User(USER_NAME_PETER, USER_EMAIL2, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE", USER_EMAIL3, INACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); List usersSortByName = userRepository.findAll(new Sort(Sort.Direction.ASC, "name")); @@ -282,9 +286,9 @@ public class UserRepositoryIntegrationTest { @Test(expected = PropertyReferenceException.class) public void givenUsersInDBWhenFindAllSortWithFunctionThenThrowException() { - userRepository.save(new User(USER_NAME_ADAM, USER_EMAIL, ACTIVE_STATUS)); - userRepository.save(new User(USER_NAME_PETER, USER_EMAIL2, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE", USER_EMAIL3, INACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); userRepository.findAll(new Sort(Sort.Direction.ASC, "name")); @@ -296,9 +300,9 @@ public class UserRepositoryIntegrationTest { @Test public void givenUsersInDBWhenFindAllSortWithFunctionQueryAnnotationJPQLThenReturnUsersSorted() { - userRepository.save(new User(USER_NAME_ADAM, USER_EMAIL, ACTIVE_STATUS)); - userRepository.save(new User(USER_NAME_PETER, USER_EMAIL2, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE", USER_EMAIL3, INACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); userRepository.findAllUsers(new Sort("name")); @@ -310,12 +314,12 @@ public class UserRepositoryIntegrationTest { @Test public void givenUsersInDBWhenFindAllWithPageRequestQueryAnnotationJPQLThenReturnPageOfUsers() { - userRepository.save(new User(USER_NAME_ADAM, USER_EMAIL, ACTIVE_STATUS)); - userRepository.save(new User(USER_NAME_PETER, USER_EMAIL2, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE", USER_EMAIL3, INACTIVE_STATUS)); - userRepository.save(new User("SAMPLE1", USER_EMAIL4, INACTIVE_STATUS)); - userRepository.save(new User("SAMPLE2", USER_EMAIL5, INACTIVE_STATUS)); - userRepository.save(new User("SAMPLE3", USER_EMAIL6, INACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL4, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE2", LocalDate.now(), USER_EMAIL5, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL6, INACTIVE_STATUS)); Page usersPage = userRepository.findAllUsersWithPagination(new PageRequest(1, 3)); @@ -326,12 +330,12 @@ public class UserRepositoryIntegrationTest { @Test public void givenUsersInDBWhenFindAllWithPageRequestQueryAnnotationNativeThenReturnPageOfUsers() { - userRepository.save(new User(USER_NAME_ADAM, USER_EMAIL, ACTIVE_STATUS)); - userRepository.save(new User(USER_NAME_PETER, USER_EMAIL2, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE", USER_EMAIL3, INACTIVE_STATUS)); - userRepository.save(new User("SAMPLE1", USER_EMAIL4, INACTIVE_STATUS)); - userRepository.save(new User("SAMPLE2", USER_EMAIL5, INACTIVE_STATUS)); - userRepository.save(new User("SAMPLE3", USER_EMAIL6, INACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_ADAM, LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User(USER_NAME_PETER, LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL4, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE2", LocalDate.now(), USER_EMAIL5, INACTIVE_STATUS)); + userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL6, INACTIVE_STATUS)); Page usersSortByNameLength = userRepository.findAllUsersWithPaginationNative(new PageRequest(1, 3)); @@ -343,10 +347,10 @@ public class UserRepositoryIntegrationTest { @Test @Transactional public void givenUsersInDBWhenUpdateStatusForNameModifyingQueryAnnotationJPQLThenModifyMatchingUsers() { - userRepository.save(new User("SAMPLE", USER_EMAIL, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE1", USER_EMAIL2, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE", USER_EMAIL3, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE3", USER_EMAIL4, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL4, ACTIVE_STATUS)); int updatedUsersSize = userRepository.updateUserSetStatusForName(INACTIVE_STATUS, "SAMPLE"); @@ -356,10 +360,10 @@ public class UserRepositoryIntegrationTest { @Test @Transactional public void givenUsersInDBWhenUpdateStatusForNameModifyingQueryAnnotationNativeThenModifyMatchingUsers() { - userRepository.save(new User("SAMPLE", USER_EMAIL, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE1", USER_EMAIL2, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE", USER_EMAIL3, ACTIVE_STATUS)); - userRepository.save(new User("SAMPLE3", USER_EMAIL4, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE1", LocalDate.now(), USER_EMAIL2, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE", LocalDate.now(), USER_EMAIL3, ACTIVE_STATUS)); + userRepository.save(new User("SAMPLE3", LocalDate.now(), USER_EMAIL4, ACTIVE_STATUS)); userRepository.flush(); int updatedUsersSize = userRepository.updateUserSetStatusForNameNative(INACTIVE_STATUS, "SAMPLE"); @@ -391,6 +395,137 @@ public class UserRepositoryIntegrationTest { assertThat(usersWithEmails.size()).isEqualTo(2); } + @Test + @Transactional + public void givenTwoUsers_whenFindByNameUsr01_ThenUserUsr01() { + User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.now(), "usr02@baeldung.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + try (Stream users = userRepository.findAllByName("usr01")) { + assertTrue(users.allMatch(usr -> usr.equals(usr01))); + } + } + + @Test + @Transactional + public void givenTwoUsers_whenFindByNameUsr00_ThenNoUsers() { + User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.now(), "usr02@baeldung.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + try (Stream users = userRepository.findAllByName("usr00")) { + assertEquals(0, users.count()); + } + } + + @Test + public void givenTwoUsers_whenFindUsersWithGmailAddress_ThenUserUsr02() { + User usr01 = new User("usr01", LocalDate.now(), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.now(), "usr02@gmail.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + List users = userRepository.findUsersWithGmailAddress(); + assertEquals(1, users.size()); + assertEquals(usr02, users.get(0)); + } + + @Test + @Transactional + public void givenTwoUsers_whenDeleteAllByCreationDateAfter_ThenOneUserRemains() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.com", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + userRepository.deleteAllByCreationDateAfter(LocalDate.of(2018, 5, 1)); + + List users = userRepository.findAll(); + + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + } + + @Test + public void givenTwoUsers_whenFindAllUsersByPredicates_ThenUserUsr01() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1); + + userRepository.save(usr01); + userRepository.save(usr02); + + List> predicates = new ArrayList<>(); + predicates.add(usr -> usr.getCreationDate().isAfter(LocalDate.of(2017, 12, 31))); + predicates.add(usr -> usr.getEmail().endsWith(".com")); + + List users = userRepository.findAllUsersByPredicates(predicates); + + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + } + + @Test + @Transactional + public void givenTwoUsers_whenDeactivateUsersNotLoggedInSince_ThenUserUsr02Deactivated() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + usr01.setLastLoginDate(LocalDate.now()); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + + userRepository.save(usr01); + userRepository.save(usr02); + + userRepository.deactivateUsersNotLoggedInSince(LocalDate.of(2018, 8, 1)); + + List users = userRepository.findAllUsers(Sort.by(Sort.Order.asc("name"))); + assertTrue(users.get(0).isActive()); + assertFalse(users.get(1).isActive()); + } + + @Test + @Transactional + public void givenTwoUsers_whenDeleteDeactivatedUsers_ThenUserUsr02Deleted() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + usr01.setLastLoginDate(LocalDate.now()); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + usr02.setActive(false); + + userRepository.save(usr01); + userRepository.save(usr02); + + userRepository.deleteDeactivatedUsers(); + + List users = userRepository.findAll(); + assertEquals(1, users.size()); + assertEquals(usr01, users.get(0)); + } + + @Test + @Transactional + public void givenTwoUsers_whenAddDeletedColumn_ThenUsersHaveDeletedColumn() { + User usr01 = new User("usr01", LocalDate.of(2018, 1, 1), "usr01@baeldung.com", 1); + usr01.setLastLoginDate(LocalDate.now()); + User usr02 = new User("usr02", LocalDate.of(2018, 6, 1), "usr02@baeldung.org", 1); + usr02.setLastLoginDate(LocalDate.of(2018, 7, 20)); + usr02.setActive(false); + + userRepository.save(usr01); + userRepository.save(usr02); + + userRepository.addDeletedColumn(); + + Query nativeQuery = entityManager.createNativeQuery("select deleted from USERS.USERS where NAME = 'usr01'"); + assertEquals(0, nativeQuery.getResultList().get(0)); + } + @After public void cleanUp() { userRepository.deleteAll(); From 29c13ca8011732eb525adbb3c823839af0f225a1 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Wed, 6 Feb 2019 11:12:14 +0800 Subject: [PATCH 020/496] BAEL-2582 Building DSLs in Kotlin * added basic SQL DSL * basic SQL DSL tests --- .../kotlin/com/baeldung/kotlin/dsl/SqlDsl.kt | 114 ++++++++++++++++++ .../com/baeldung/kotlin/dsl/SqlDslTest.kt | 74 ++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 core-kotlin/src/main/kotlin/com/baeldung/kotlin/dsl/SqlDsl.kt create mode 100644 core-kotlin/src/test/kotlin/com/baeldung/kotlin/dsl/SqlDslTest.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/dsl/SqlDsl.kt b/core-kotlin/src/main/kotlin/com/baeldung/kotlin/dsl/SqlDsl.kt new file mode 100644 index 0000000000..5296d301a3 --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/kotlin/dsl/SqlDsl.kt @@ -0,0 +1,114 @@ +package com.baeldung.kotlin.dsl + +abstract class Condition { + + fun and(initializer: Condition.() -> Unit) { + addCondition(And().apply(initializer)) + } + + fun or(initializer: Condition.() -> Unit) { + addCondition(Or().apply(initializer)) + } + + infix fun String.eq(value: Any?) { + addCondition(Eq(this, value)) + } + + protected abstract fun addCondition(condition: Condition) +} + +open class CompositeCondition(private val sqlOperator: String) : Condition() { + private val conditions = mutableListOf() + + override fun addCondition(condition: Condition) { + conditions += condition + } + + override fun toString(): String { + return if (conditions.size == 1) { + conditions.first().toString() + } else { + conditions.joinToString(prefix = "(", postfix = ")", separator = " $sqlOperator ") { + "$it" + } + } + } +} + +class And : CompositeCondition("and") + +class Or : CompositeCondition("or") + +class Eq(private val column: String, private val value: Any?) : Condition() { + + init { + if (value != null && value !is Number && value !is String) { + throw IllegalArgumentException("Only , numbers and strings values can be used in the 'where' clause") + } + } + + override fun addCondition(condition: Condition) { + throw IllegalStateException("Can't add a nested condition to the sql 'eq'") + } + + override fun toString(): String { + return when (value) { + null -> "$column is null" + is String -> "$column = '$value'" + else -> "$column = $value" + } + } +} + +class SqlSelectBuilder { + + private val columns = mutableListOf() + private lateinit var table: String + private var condition: Condition? = null + + fun select(vararg columns: String) { + if (columns.isEmpty()) { + throw IllegalArgumentException("At least one column should be defined") + } + if (this.columns.isNotEmpty()) { + throw IllegalStateException("Detected an attempt to re-define columns to fetch. Current columns list: " + + "${this.columns}, new columns list: $columns") + } + this.columns.addAll(columns) + } + + fun from(table: String) { + this.table = table + } + + fun where(initializer: Condition.() -> Unit) { + condition = And().apply(initializer) + } + + fun build(): String { + if (!::table.isInitialized) { + throw IllegalStateException("Failed to build an sql select - target table is undefined") + } + return toString() + } + + override fun toString(): String { + val columnsToFetch = + if (columns.isEmpty()) { + "*" + } else { + columns.joinToString(", ") + } + val conditionString = + if (condition == null) { + "" + } else { + " where $condition" + } + return "select $columnsToFetch from $table$conditionString" + } +} + +fun query(initializer: SqlSelectBuilder.() -> Unit): SqlSelectBuilder { + return SqlSelectBuilder().apply(initializer) +} \ No newline at end of file diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/dsl/SqlDslTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/dsl/SqlDslTest.kt new file mode 100644 index 0000000000..55ae44e4dc --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/dsl/SqlDslTest.kt @@ -0,0 +1,74 @@ +package com.baeldung.kotlin.dsl + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test +import java.lang.Exception + +class SqlDslTest { + + @Test + fun `when no columns are specified then star is used`() { + doTest("select * from table1") { + from ("table1") + } + } + + @Test + fun `when no condition is specified then correct query is built`() { + doTest("select column1, column2 from table1") { + select("column1", "column2") + from ("table1") + } + } + + @Test(expected = Exception::class) + fun `when no table is specified then an exception is thrown`() { + query { + select("column1") + }.build() + } + + @Test + fun `when a list of conditions is specified then it's respected`() { + doTest("select * from table1 where (column3 = 4 and column4 is null)") { + from ("table1") + where { + "column3" eq 4 + "column4" eq null + } + } + } + + @Test + fun `when 'or' conditions are specified then they are respected`() { + doTest("select * from table1 where (column3 = 4 or column4 is null)") { + from ("table1") + where { + or { + "column3" eq 4 + "column4" eq null + } + } + } + } + + @Test + fun `when either 'and' or 'or' conditions are specified then they are respected`() { + doTest("select * from table1 where ((column3 = 4 or column4 is null) and column5 = 42)") { + from ("table1") + where { + and { + or { + "column3" eq 4 + "column4" eq null + } + "column5" eq 42 + } + } + } + } + + private fun doTest(expected: String, sql: SqlSelectBuilder.() -> Unit) { + assertThat(query(sql).build()).isEqualTo(expected) + } +} \ No newline at end of file From 3704450509574b98c33bf504090d514754e8e592 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Fri, 8 Feb 2019 14:55:23 +0400 Subject: [PATCH 021/496] more tests --- .../performance/ArraySortBenchmark.java | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java index 5f126fd67d..875a122c82 100644 --- a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java +++ b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java @@ -22,30 +22,48 @@ public class ArraySortBenchmark { int iterations = 1000; - int[] array = new int[iterations]; - List list = new ArrayList<>(); + String[] array = new String[iterations]; + List list = new ArrayList<>(); + + int[] intArray = new int[iterations]; + List integerList = new ArrayList<>(); @Setup(Level.Trial) public void setUp() { for (int i = 0; i < iterations; i++) { - array[i] = i; - list.add(i); + array[i] = i + ""; + list.add(i + ""); + + intArray[i] = i; + integerList.add(i); } } } @Benchmark - public int[] benchmarkArraysSort(ArraySortBenchmark.Initialize state) { + public String[] benchmarkArraysSort(ArraySortBenchmark.Initialize state) { Arrays.sort(state.array); return state.array; } @Benchmark - public List benchmarkCollectionsSort(ArraySortBenchmark.Initialize state) { + public List benchmarkCollectionsSort(ArraySortBenchmark.Initialize state) { Collections.sort(state.list); return state.list; } + @Benchmark + public int[] benchmarkArraysSortInt(ArraySortBenchmark.Initialize state) { + Arrays.sort(state.intArray); + return state.intArray; + } + + @Benchmark + public List benchmarkCollectionsSortInteger(ArraySortBenchmark.Initialize state) { + Collections.sort(state.integerList); + return state.integerList; + } + public static void main(String[] args) throws Exception { Options options = new OptionsBuilder() .include(ArraySortBenchmark.class.getSimpleName()).threads(1) From 648e66d9e3c799cc44e87d22d4199cb9e0debd55 Mon Sep 17 00:00:00 2001 From: Yatendra Goel Date: Sun, 10 Feb 2019 02:54:20 +0530 Subject: [PATCH 022/496] BAEL-1915: Upgraded from Boot1 to Boot2 --- spring-boot-security/pom.xml | 10 ++++++++-- .../basic_auth/SpringBootSecurityApplication.java | 2 +- .../basic_auth/config/BasicAuthConfiguration.java | 9 ++++++--- .../BasicAuthConfigurationIntegrationTest.java | 4 +--- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/spring-boot-security/pom.xml b/spring-boot-security/pom.xml index b87189757a..ec442f8dd1 100644 --- a/spring-boot-security/pom.xml +++ b/spring-boot-security/pom.xml @@ -8,10 +8,10 @@ Spring Boot Security Auto-Configuration - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -22,6 +22,12 @@ org.springframework.security.oauth spring-security-oauth2 + 2.3.3.RELEASE + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + 2.1.2.RELEASE org.springframework.boot diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java index 2ecad4ae35..4666ca4fbd 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java @@ -2,7 +2,7 @@ package com.baeldung.springbootsecurity.basic_auth; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; @SpringBootApplication(exclude = { SecurityAutoConfiguration.class diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java index 993c573fb0..592ef5354d 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java @@ -5,6 +5,8 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @@ -12,14 +14,15 @@ public class BasicAuthConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth + PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); + auth .inMemoryAuthentication() .withUser("user") - .password("password") + .password(encoder.encode("password")) .roles("USER") .and() .withUser("admin") - .password("admin") + .password(encoder.encode("admin")) .roles("USER", "ADMIN"); } diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java index 32c3fbdef4..94cf9f4148 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java @@ -1,12 +1,11 @@ package com.baeldung.springbootsecurity.basic_auth; -import com.baeldung.springbootsecurity.basic_auth.SpringBootSecurityApplication; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.context.embedded.LocalServerPort; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; @@ -18,7 +17,6 @@ import java.net.URL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootSecurityApplication.class) public class BasicAuthConfigurationIntegrationTest { From 540f96acb085ce3675cbe6fd77bbf94a729b5536 Mon Sep 17 00:00:00 2001 From: markoprevisic Date: Sun, 10 Feb 2019 20:34:45 +0100 Subject: [PATCH 023/496] [BAEL-2533] formatting json date output in spring boot --- .../com/baeldung/jsondateformat/Contact.java | 70 ++++++++++++++ .../baeldung/jsondateformat/ContactApp.java | 13 +++ .../jsondateformat/ContactAppConfig.java | 33 +++++++ .../jsondateformat/ContactController.java | 77 +++++++++++++++ .../ContactWithJavaUtilDate.java | 69 +++++++++++++ .../baeldung/jsondateformat/PlainContact.java | 66 +++++++++++++ .../PlainContactWithJavaUtilDate.java | 69 +++++++++++++ .../org/baeldung/demo/boottest/Employee.java | 3 + .../src/main/resources/application.properties | 2 + .../ContactAppIntegrationTest.java | 96 +++++++++++++++++++ ...ObjectMapperCustomizerIntegrationTest.java | 64 +++++++++++++ 11 files changed, 562 insertions(+) create mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/Contact.java create mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/ContactApp.java create mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java create mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/ContactController.java create mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java create mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContact.java create mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java create mode 100644 spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java create mode 100644 spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/Contact.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/Contact.java new file mode 100644 index 0000000000..f131d17196 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/jsondateformat/Contact.java @@ -0,0 +1,70 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class Contact { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private LocalDate birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public LocalDateTime getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(LocalDateTime lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public Contact() { + } + + public Contact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactApp.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactApp.java new file mode 100644 index 0000000000..79037e1038 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactApp.java @@ -0,0 +1,13 @@ +package com.baeldung.jsondateformat; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ContactApp { + + public static void main(String[] args) { + SpringApplication.run(ContactApp.class, args); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java new file mode 100644 index 0000000000..7a20ebfa51 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java @@ -0,0 +1,33 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.time.format.DateTimeFormatter; + +@Configuration +public class ContactAppConfig { + + private static final String dateFormat = "yyyy-MM-dd"; + + private static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; + + @Bean + @ConditionalOnProperty(value = "spring.jackson.date-format", matchIfMissing = true, havingValue = "none") + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + return new Jackson2ObjectMapperBuilderCustomizer() { + @Override + public void customize(Jackson2ObjectMapperBuilder builder) { + builder.simpleDateFormat(dateTimeFormat); + builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat))); + builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat))); + } + }; + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactController.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactController.java new file mode 100644 index 0000000000..8894d82fc7 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactController.java @@ -0,0 +1,77 @@ +package com.baeldung.jsondateformat; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@RestController +@RequestMapping(value = "/contacts") +public class ContactController { + + @GetMapping + public List getContacts() { + List contacts = new ArrayList<>(); + + Contact contact1 = new Contact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + Contact contact2 = new Contact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + Contact contact3 = new Contact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/javaUtilDate") + public List getContactsWithJavaUtilDate() { + List contacts = new ArrayList<>(); + + ContactWithJavaUtilDate contact1 = new ContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); + ContactWithJavaUtilDate contact2 = new ContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); + ContactWithJavaUtilDate contact3 = new ContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/plain") + public List getPlainContacts() { + List contacts = new ArrayList<>(); + + PlainContact contact1 = new PlainContact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + PlainContact contact2 = new PlainContact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + PlainContact contact3 = new PlainContact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/plainWithJavaUtilDate") + public List getPlainContactsWithJavaUtilDate() { + List contacts = new ArrayList<>(); + + PlainContactWithJavaUtilDate contact1 = new PlainContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); + PlainContactWithJavaUtilDate contact2 = new PlainContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); + PlainContactWithJavaUtilDate contact3 = new PlainContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java new file mode 100644 index 0000000000..5a1c508098 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java @@ -0,0 +1,69 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class ContactWithJavaUtilDate { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Date getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(Date lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public ContactWithJavaUtilDate() { + } + + public ContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContact.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContact.java new file mode 100644 index 0000000000..7e9e53d205 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContact.java @@ -0,0 +1,66 @@ +package com.baeldung.jsondateformat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class PlainContact { + + private String name; + private String address; + private String phone; + + private LocalDate birthday; + + private LocalDateTime lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public LocalDateTime getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(LocalDateTime lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public PlainContact() { + } + + public PlainContact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java new file mode 100644 index 0000000000..daefb15543 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java @@ -0,0 +1,69 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class PlainContactWithJavaUtilDate { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Date getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(Date lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public PlainContactWithJavaUtilDate() { + } + + public PlainContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot/src/main/java/org/baeldung/demo/boottest/Employee.java b/spring-boot/src/main/java/org/baeldung/demo/boottest/Employee.java index c1dd109f91..645ce2838a 100644 --- a/spring-boot/src/main/java/org/baeldung/demo/boottest/Employee.java +++ b/spring-boot/src/main/java/org/baeldung/demo/boottest/Employee.java @@ -6,6 +6,7 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import javax.validation.constraints.Size; +import java.util.Date; @Entity @Table(name = "person") @@ -25,6 +26,8 @@ public class Employee { @Size(min = 3, max = 20) private String name; + private Date birthday; + public Long getId() { return id; } diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 6a52dd1f70..00c251d823 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -73,3 +73,5 @@ chaos.monkey.watcher.repository=false #Component watcher active chaos.monkey.watcher.component=false +spring.jackson.date-format=yyyy-MM-dd HH:mm:ss +spring.jackson.time-zone=Europe/Zagreb diff --git a/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java new file mode 100644 index 0000000000..86af985d8a --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java @@ -0,0 +1,96 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.text.ParseException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = DEFINED_PORT, classes = ContactApp.class) +@TestPropertySource(properties = { + "spring.jackson.date-format=yyyy-MM-dd HH:mm:ss" +}) +public class ContactAppIntegrationTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + @Autowired + TestRestTemplate restTemplate; + + @Test + public void givenJsonFormatAnnotationAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException, ParseException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenJsonFormatAnnotationAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/javaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/plainWithJavaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test(expected = DateTimeParseException.class) + public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenNotApplyFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/plain", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } + +} diff --git a/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java new file mode 100644 index 0000000000..d88c84bbbf --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java @@ -0,0 +1,64 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = DEFINED_PORT, classes = ContactApp.class) +public class ContactAppWithObjectMapperCustomizerIntegrationTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + @Autowired + TestRestTemplate restTemplate; + + @Test + public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/plainWithJavaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/plain", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + +} From 185a7f0e18c877609887e3513999516f14bfd79f Mon Sep 17 00:00:00 2001 From: markoprevisic Date: Sun, 10 Feb 2019 20:37:41 +0100 Subject: [PATCH 024/496] [BAEL-2533] removed unused import --- .../ContactAppWithObjectMapperCustomizerIntegrationTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java index d88c84bbbf..554283d758 100644 --- a/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java +++ b/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java @@ -8,7 +8,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.http.ResponseEntity; -import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import java.io.IOException; From 12b19733afae15d6455a598ba7f239ebd0b5273d Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 11 Feb 2019 16:04:40 +0400 Subject: [PATCH 025/496] primitive list benchmark tests --- core-java-collections-list/pom.xml | 11 +++ .../primitive/PrimitivesListPerformance.java | 96 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java diff --git a/core-java-collections-list/pom.xml b/core-java-collections-list/pom.xml index 737be8ee34..b9b6f4a6a6 100644 --- a/core-java-collections-list/pom.xml +++ b/core-java-collections-list/pom.xml @@ -52,6 +52,17 @@ colt ${colt.version} + + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-core.version} + diff --git a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java new file mode 100644 index 0000000000..1d4d0e250d --- /dev/null +++ b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java @@ -0,0 +1,96 @@ +package com.baeldung.list.primitive; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import gnu.trove.list.array.TIntArrayList; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Measurement(batchSize = 100000, iterations = 10) +@Warmup(batchSize = 100000, iterations = 10) +@State(Scope.Thread) +public class PrimitivesListPerformance { + + private List arrayList = new ArrayList<>(); + private TIntArrayList tList = new TIntArrayList(); + private cern.colt.list.IntArrayList coltList = new cern.colt.list.IntArrayList(); + private IntArrayList fastUtilList = new IntArrayList(); + + private int getValue = 10; + + @Benchmark + public boolean addArrayList() { + return arrayList.add(getValue); + } + + @Benchmark + public boolean addTIntList() { + return tList.add(getValue); + } + + @Benchmark + public void addColtIntList() { + coltList.add(getValue); + } + + @Benchmark + public boolean addFastUtilIntList() { + return fastUtilList.add(getValue); + } + + @Benchmark + public int getArrayList() { + return arrayList.get(getValue); + } + + @Benchmark + public int getTIntList() { + return tList.get(getValue); + } + + @Benchmark + public int getColtIntList() { + return coltList.get(getValue); + } + + @Benchmark + public int getFastUtilIntList() { + return fastUtilList.getInt(getValue); + } + + @Benchmark + public boolean containsArrayList() { + return arrayList.contains(getValue); + } + + @Benchmark + public boolean containsTIntList() { + return tList.contains(getValue); + } + + @Benchmark + public boolean containsColtIntList() { + return coltList.contains(getValue); + } + + @Benchmark + public boolean containsFastUtilIntList() { + return fastUtilList.contains(getValue); + } + + public static void main(String[] args) throws Exception { + Options options = new OptionsBuilder() + .include(PrimitivesListPerformance.class.getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true) + .shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } +} From 355e206965cecf36f34a4d3a2301fbc63ef8e057 Mon Sep 17 00:00:00 2001 From: clininger Date: Mon, 11 Feb 2019 19:24:22 +0700 Subject: [PATCH 026/496] BAEL-2731 - Testing Web APIs with Postman Collections --- postman/testing-api-with-collection/README.md | 3 + .../foo API test.postman_collection.json | 184 ++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 postman/testing-api-with-collection/README.md create mode 100644 postman/testing-api-with-collection/foo API test.postman_collection.json diff --git a/postman/testing-api-with-collection/README.md b/postman/testing-api-with-collection/README.md new file mode 100644 index 0000000000..04d30e4240 --- /dev/null +++ b/postman/testing-api-with-collection/README.md @@ -0,0 +1,3 @@ +# Testing Web APIs with Postman Collections + +Import the collection into Postman. \ No newline at end of file diff --git a/postman/testing-api-with-collection/foo API test.postman_collection.json b/postman/testing-api-with-collection/foo API test.postman_collection.json new file mode 100644 index 0000000000..cd9454c218 --- /dev/null +++ b/postman/testing-api-with-collection/foo API test.postman_collection.json @@ -0,0 +1,184 @@ +{ + "info": { + "_postman_id": "9989b5be-13ba-4d22-8e43-d05dbf628e58", + "name": "foo API test", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "add a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "a01534dc-6fc7-4c54-ba1d-6bcf311e5836", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );", + "", + "pm.test(\"name is correct\", () => ", + " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", + "", + "pm.test(\"id was assigned\", () => ", + " pm.expect(pm.response.json().id).to.be.not.null );", + "", + "pm.variables.set(\"id\", pm.response.json().id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Transformers\"\n}" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos" + ] + } + }, + "response": [] + }, + { + "name": "get a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "03de440c-b483-4ab8-a11a-d0c99b349963", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );", + "", + "pm.test(\"name is correct\", () => ", + " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", + "", + "pm.test(\"id is correct\", () => ", + " pm.expect(pm.response.json().id).to.equal(pm.variables.get(\"id\")) );" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "delete a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "74c1bb0f-c06c-48b1-a545-459233541b14", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "verify delete", + "event": [ + { + "listen": "test", + "script": { + "id": "03de440c-b483-4ab8-a11a-d0c99b349963", + "exec": [ + "pm.test(\"status is 500\", () => pm.response.to.have.status(500) );", + "", + "pm.test(\"no value present\", () => ", + " pm.expect(pm.response.json().cause).to.equal(\"No value present\"));" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file From b4041f577d9a42f7656f664ac42b010e76f470a8 Mon Sep 17 00:00:00 2001 From: Venkata Kiran Surapaneni Date: Mon, 11 Feb 2019 08:28:20 -0500 Subject: [PATCH 027/496] Made holdability example much clear. --- .../com/baeldung/jdbc/ResultSetLiveTest.java | 65 +++++++++++++------ 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java index 2762aeda5e..4e10f8bd43 100644 --- a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java +++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/ResultSetLiveTest.java @@ -175,54 +175,60 @@ public class ResultSetLiveTest { @Test public void givenDbConnectionJ_whenClosedCursor_thenCorrect() throws SQLException { - int numOfRows = 0; + Employee employee = null; dbConnection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT)) { dbConnection.setAutoCommit(false); - pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Chris',2100.0,'Manager')"); ResultSet rs = pstmt.executeQuery("select * from employees"); - dbConnection.commit(); while (rs.next()) { - Employee employee = populateResultSet(rs); + if (rs.getString("name") + .equalsIgnoreCase("john")) { + rs.updateString("position", "Senior Engineer"); + rs.updateRow(); + dbConnection.commit(); + employee = populateResultSet(rs); + } } rs.last(); - numOfRows = rs.getRow(); } - assertEquals("Inserted using close cursor after commit", 3, numOfRows); + assertEquals("Update using closed cursor", "Senior Engineer", employee.getPosition()); } @Test public void givenDbConnectionK_whenUpdate_thenCorrect() throws SQLException { - int numOfRows = 0; + Employee employee = null; dbConnection.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); try (Statement pstmt = dbConnection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE, ResultSet.HOLD_CURSORS_OVER_COMMIT)) { dbConnection.setAutoCommit(false); - pstmt.executeUpdate("INSERT INTO employees (name, salary,position) VALUES ('Michael',1200.0,'Consultant')"); ResultSet rs = pstmt.executeQuery("select * from employees"); - dbConnection.commit(); while (rs.next()) { - Employee employee = populateResultSet(rs); + if (rs.getString("name") + .equalsIgnoreCase("john")) { + rs.updateString("name", "John Doe"); + rs.updateRow(); + dbConnection.commit(); + employee = populateResultSet(rs); + } } rs.last(); - numOfRows = rs.getRow(); } - assertEquals("Inserted using hold cursor after commit", 4, numOfRows); + assertEquals("Update using open cursor", "John Doe", employee.getName()); } @Test public void givenDbConnectionM_whenDelete_thenCorrect() throws SQLException { int numOfRows = 0; try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { - rs.absolute(3); + rs.absolute(2); rs.deleteRow(); } try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { rs.last(); numOfRows = rs.getRow(); } - assertEquals("Deleted row", 3, numOfRows); + assertEquals("Deleted row", 1, numOfRows); } @Test @@ -231,12 +237,33 @@ public class ResultSetLiveTest { try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { - Assert.assertEquals(1000.0, rs.getDouble("salary")); + Assert.assertEquals(1100.0, rs.getDouble("salary")); - rs.updateDouble("salary", 1100.0); + rs.updateDouble("salary", 1200.0); rs.updateRow(); - Assert.assertEquals(1100.0, rs.getDouble("salary")); + Assert.assertEquals(1200.0, rs.getDouble("salary")); + + String name = rs.getString("name"); + Integer empId = rs.getInt("emp_id"); + Double salary = rs.getDouble("salary"); + String position = rs.getString("position"); + employee = new Employee(empId, name, salary, position); + } + } + } + + @Test + public void givenDbConnectionC_whenUpdateByIndex_thenCorrect() throws SQLException { + Employee employee = null; + try (PreparedStatement pstmt = dbConnection.prepareStatement("select * from employees", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstmt.executeQuery()) { + while (rs.next()) { + + Assert.assertEquals(1000.0, rs.getDouble(4)); + + rs.updateDouble(4, 1100.0); + rs.updateRow(); + Assert.assertEquals(1100.0, rs.getDouble(4)); String name = rs.getString("name"); Integer empId = rs.getInt("emp_id"); @@ -320,7 +347,7 @@ public class ResultSetLiveTest { pstmt.close(); } - assertEquals(4, listOfEmployees.size()); + assertEquals(2, listOfEmployees.size()); } @AfterClass @@ -329,4 +356,4 @@ public class ResultSetLiveTest { deleteStmt.execute(); dbConnection.close(); } -} +} \ No newline at end of file From 9e3a1cadd17a7a405f316a4c9deb615c0b5ef2a2 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Tue, 12 Feb 2019 22:26:45 +0200 Subject: [PATCH 028/496] Update README.md --- core-kotlin-2/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core-kotlin-2/README.md b/core-kotlin-2/README.md index ff12555376..6aabd71a6c 100644 --- a/core-kotlin-2/README.md +++ b/core-kotlin-2/README.md @@ -1 +1,3 @@ ## Relevant articles: + +- [Void Type in Kotlin](https://www.baeldung.com/kotlin-void-type) From 337a5dfbc87b3d63fb08085d2fd94c548539433d Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Wed, 13 Feb 2019 13:03:57 +0400 Subject: [PATCH 029/496] changed examples of sort() --- .../performance/ArraySortBenchmark.java | 39 +++++-------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java index 875a122c82..14cef2406a 100644 --- a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java +++ b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java @@ -20,48 +20,27 @@ public class ArraySortBenchmark { @State(Scope.Thread) public static class Initialize { - int iterations = 1000; - - String[] array = new String[iterations]; - List list = new ArrayList<>(); - - int[] intArray = new int[iterations]; - List integerList = new ArrayList<>(); + String[] words = {"Java", "Baeldung", "Tutorial"}; + List wordList = new ArrayList<>(); @Setup(Level.Trial) public void setUp() { - for (int i = 0; i < iterations; i++) { - array[i] = i + ""; - list.add(i + ""); - - intArray[i] = i; - integerList.add(i); - } + wordList.add("Java"); + wordList.add("Baeldung"); + wordList.add("Tutorial"); } } @Benchmark public String[] benchmarkArraysSort(ArraySortBenchmark.Initialize state) { - Arrays.sort(state.array); - return state.array; + Arrays.sort(state.words); + return state.words; } @Benchmark public List benchmarkCollectionsSort(ArraySortBenchmark.Initialize state) { - Collections.sort(state.list); - return state.list; - } - - @Benchmark - public int[] benchmarkArraysSortInt(ArraySortBenchmark.Initialize state) { - Arrays.sort(state.intArray); - return state.intArray; - } - - @Benchmark - public List benchmarkCollectionsSortInteger(ArraySortBenchmark.Initialize state) { - Collections.sort(state.integerList); - return state.integerList; + Collections.sort(state.wordList); + return state.wordList; } public static void main(String[] args) throws Exception { From 5eaffaec0e285ae7462621f34cb26e993943ebc5 Mon Sep 17 00:00:00 2001 From: clininger Date: Wed, 13 Feb 2019 21:49:24 +0700 Subject: [PATCH 030/496] BAEL-2731 - moved postman script to spring-boot-rest project --- postman/testing-api-with-collection/README.md | 3 --- .../src/test/resources/foo_API_test.postman_collection.json | 0 2 files changed, 3 deletions(-) delete mode 100644 postman/testing-api-with-collection/README.md rename postman/testing-api-with-collection/foo API test.postman_collection.json => spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json (100%) diff --git a/postman/testing-api-with-collection/README.md b/postman/testing-api-with-collection/README.md deleted file mode 100644 index 04d30e4240..0000000000 --- a/postman/testing-api-with-collection/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Testing Web APIs with Postman Collections - -Import the collection into Postman. \ No newline at end of file diff --git a/postman/testing-api-with-collection/foo API test.postman_collection.json b/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json similarity index 100% rename from postman/testing-api-with-collection/foo API test.postman_collection.json rename to spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json From 7e843727b971298db82909d142a80bf10c84bb66 Mon Sep 17 00:00:00 2001 From: macroscopic64 Date: Thu, 14 Feb 2019 08:36:11 +0530 Subject: [PATCH 031/496] simplified the leap year check logic --- .../java/com/baeldung/multireleaseapp/App.java | 7 ++++++- .../baeldung/multireleaseapp/DateHelper.java | 18 ++++++++---------- .../baeldung/multireleaseapp/DateHelper.java | 7 ++++++- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java b/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java index c2e738384a..21bbcc01d4 100644 --- a/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java +++ b/core-java-9/src/main/java/com/baeldung/multireleaseapp/App.java @@ -1,11 +1,16 @@ package com.baeldung.multireleaseapp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class App { + private static final Logger logger = LoggerFactory.getLogger(App.class); + public static void main(String[] args) throws Exception { String dateToCheck = args[0]; boolean isLeapYear = DateHelper.checkIfLeapYear(dateToCheck); - System.out.println("Date given " + dateToCheck + " is leap year: " + isLeapYear); + logger.info("Date given " + dateToCheck + " is leap year: " + isLeapYear); } } diff --git a/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java b/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java index 842ac00350..4d943db30b 100644 --- a/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java +++ b/core-java-9/src/main/java/com/baeldung/multireleaseapp/DateHelper.java @@ -2,23 +2,21 @@ package com.baeldung.multireleaseapp; import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.GregorianCalendar; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DateHelper { + private static final Logger logger = LoggerFactory.getLogger(DateHelper.class); + public static boolean checkIfLeapYear(String dateStr) throws Exception { - System.out.println("Checking for leap year using Java 1 calendar API "); - boolean isLeapYear = false; + logger.info("Checking for leap year using Java 1 calendar API"); Calendar cal = Calendar.getInstance(); cal.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(dateStr)); int year = cal.get(Calendar.YEAR); - if (year % 4 == 0) { - if (year % 100 == 0) { - isLeapYear = (year % 400 == 0) ? true : false; - } else { - isLeapYear = true; - } - } - return isLeapYear; + return (new GregorianCalendar()).isLeapYear(year); } } diff --git a/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java b/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java index 1d8a10f145..35fb0ada1e 100644 --- a/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java +++ b/core-java-9/src/main/java9/com/baeldung/multireleaseapp/DateHelper.java @@ -2,10 +2,15 @@ package com.baeldung.multireleaseapp; import java.time.LocalDate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class DateHelper { + private static final Logger logger = LoggerFactory.getLogger(DateHelper.class); + public static boolean checkIfLeapYear(String dateStr) throws Exception { - System.out.println("Checking for leap year using Java 9 Date Api"); + logger.info("Checking for leap year using Java 9 Date Api"); return LocalDate.parse(dateStr) .isLeapYear(); } From 22b57081b7fac00138caa958e58b4489a84e4cee Mon Sep 17 00:00:00 2001 From: Sushant Date: Thu, 14 Feb 2019 23:21:11 +0100 Subject: [PATCH 032/496] Add tests for string comparison --- .../stringcomparison/StringComparisonTest.kt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt new file mode 100644 index 0000000000..b8eefdb144 --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt @@ -0,0 +1,47 @@ +package com.baeldung.stringcomparison + +import org.junit.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class StringComparisonUnitTest { + + @Test + fun compareUsingEqualsOperator() { + val first = "kotlin" + val second = "kotlin" + val firstCapitalized = "KOTLIN" + assertTrue { first == second } + assertFalse { first == firstCapitalized } + } + + @Test + fun compareUsingReferencialEqualsOperator() { + val first = "kotlin" + val second = "kotlin" + val firstBuildAgain = buildString { "kotlin" } + assertTrue { first === second } + assertFalse { first === firstBuildAgain } + } + + @Test + fun compareUsingEqualsMethod() { + val first = "kotlin" + val second = "kotlin" + val firstCapitalized = "KOTLIN" + assertTrue { first.equals(second) } + assertFalse { first.equals(firstCapitalized) } + assertTrue { first.equals(firstCapitalized, true) } + } + + @Test + fun compareUsingCompareToMethod() { + val first = "kotlin" + val second = "kotlin" + val firstCapitalized = "KOTLIN" + assertTrue { first.compareTo(second) == 0 } + assertTrue { first.compareTo(firstCapitalized) == 32 } + assertTrue { firstCapitalized.compareTo(first) == -32 } + assertTrue { first.compareTo(firstCapitalized, true) == 0 } + } +} \ No newline at end of file From c5a0ff9313a079e0649a2af228c269f69ef52766 Mon Sep 17 00:00:00 2001 From: Sushant Date: Thu, 14 Feb 2019 23:31:55 +0100 Subject: [PATCH 033/496] Fix method names --- .../test/kotlin/com/baeldung/datamapping/UserTest.kt | 2 +- .../baeldung/stringcomparison/StringComparisonTest.kt | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt index 44d350ea38..c65b74ac2d 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt @@ -8,7 +8,7 @@ class UserTest { @Test fun `maps User to UserResponse using extension function`() { - val p = buildUser() + val p = buildUser() val view = p.toUserView() assertUserView(view) } diff --git a/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt index b8eefdb144..43caddfcf5 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt @@ -7,8 +7,8 @@ import kotlin.test.assertTrue class StringComparisonUnitTest { @Test - fun compareUsingEqualsOperator() { - val first = "kotlin" + fun `compare using equals operator`() { + val first = "kotlin" val second = "kotlin" val firstCapitalized = "KOTLIN" assertTrue { first == second } @@ -16,7 +16,7 @@ class StringComparisonUnitTest { } @Test - fun compareUsingReferencialEqualsOperator() { + fun `compare using referential equals operator`() { val first = "kotlin" val second = "kotlin" val firstBuildAgain = buildString { "kotlin" } @@ -25,7 +25,7 @@ class StringComparisonUnitTest { } @Test - fun compareUsingEqualsMethod() { + fun `compare using equals method`() { val first = "kotlin" val second = "kotlin" val firstCapitalized = "KOTLIN" @@ -35,7 +35,7 @@ class StringComparisonUnitTest { } @Test - fun compareUsingCompareToMethod() { + fun `compare using compare method`() { val first = "kotlin" val second = "kotlin" val firstCapitalized = "KOTLIN" From da033e6c01bcf8eea59f337448f2a35cc03e0b5a Mon Sep 17 00:00:00 2001 From: Kumar Sushant Date: Thu, 14 Feb 2019 23:33:03 +0100 Subject: [PATCH 034/496] Update UserTest.kt --- .../src/test/kotlin/com/baeldung/datamapping/UserTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt index c65b74ac2d..aeff7c8cce 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt @@ -8,7 +8,7 @@ class UserTest { @Test fun `maps User to UserResponse using extension function`() { - val p = buildUser() + val p = buildUser() val view = p.toUserView() assertUserView(view) } @@ -40,4 +40,4 @@ class UserTest { { assertEquals(30, pr.age) } ) } -} \ No newline at end of file +} From b70ff29759b42b898054e94e93e7526bd4069515 Mon Sep 17 00:00:00 2001 From: Sushant Date: Thu, 14 Feb 2019 23:35:18 +0100 Subject: [PATCH 035/496] Revert commit --- .../src/test/kotlin/com/baeldung/datamapping/UserTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt index c65b74ac2d..44d350ea38 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/datamapping/UserTest.kt @@ -8,7 +8,7 @@ class UserTest { @Test fun `maps User to UserResponse using extension function`() { - val p = buildUser() + val p = buildUser() val view = p.toUserView() assertUserView(view) } From 74e52749d49ab744f6bf8e6cc1977536b3e5e14b Mon Sep 17 00:00:00 2001 From: Sushant Date: Thu, 14 Feb 2019 23:40:01 +0100 Subject: [PATCH 036/496] Formatting --- .../com/baeldung/stringcomparison/StringComparisonTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt index 43caddfcf5..1ba98da8dd 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt @@ -8,7 +8,7 @@ class StringComparisonUnitTest { @Test fun `compare using equals operator`() { - val first = "kotlin" + val first = "kotlin" val second = "kotlin" val firstCapitalized = "KOTLIN" assertTrue { first == second } From 04f9b44a63b254803d5b8ea1a182d8932c93f1b8 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Fri, 15 Feb 2019 12:25:35 +0400 Subject: [PATCH 037/496] Trove test refactor --- .../baeldung/list/primitive/PrimitivesListPerformance.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java index 1d4d0e250d..bd37e5e74e 100644 --- a/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java +++ b/core-java-collections-list/src/main/java/com/baeldung/list/primitive/PrimitivesListPerformance.java @@ -31,7 +31,7 @@ public class PrimitivesListPerformance { } @Benchmark - public boolean addTIntList() { + public boolean addTroveIntList() { return tList.add(getValue); } @@ -51,7 +51,7 @@ public class PrimitivesListPerformance { } @Benchmark - public int getTIntList() { + public int getTroveIntList() { return tList.get(getValue); } @@ -71,7 +71,7 @@ public class PrimitivesListPerformance { } @Benchmark - public boolean containsTIntList() { + public boolean containsTroveIntList() { return tList.contains(getValue); } From fc88c99537ce2f4bb3b08b9e3da1da82e5bc9ee6 Mon Sep 17 00:00:00 2001 From: Joel Juarez Date: Fri, 15 Feb 2019 22:53:52 +0100 Subject: [PATCH 038/496] fixed README file changed filter to match url pattern --- javax-servlets-3/Dockerfile | 2 +- javax-servlets-3/README.md | 3 ++- javax-servlets-3/pom.xml | 1 + .../servlets3/web/filters/EmptyParamFilter.java | 17 ++++------------- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/javax-servlets-3/Dockerfile b/javax-servlets-3/Dockerfile index 97cc1897dd..27d1450acb 100644 --- a/javax-servlets-3/Dockerfile +++ b/javax-servlets-3/Dockerfile @@ -1,2 +1,2 @@ FROM tomcat -ADD ./target/javax-servlets-3-1.0-SNAPSHOT.war /usr/local/tomcat/webapps/ \ No newline at end of file +ADD ./target/uppercasing-app.war /usr/local/tomcat/webapps/ \ No newline at end of file diff --git a/javax-servlets-3/README.md b/javax-servlets-3/README.md index ff310b5928..1f4855f4b3 100644 --- a/javax-servlets-3/README.md +++ b/javax-servlets-3/README.md @@ -3,7 +3,8 @@ mvn package ## Run with Tomcat on Docker container: docker build --tag my-tomcat . + docker run -it --rm -p 8080:8080 my-tomcat -### Relevant Articles: +## Relevant Articles: - [Java Web Application Without Web.xml] diff --git a/javax-servlets-3/pom.xml b/javax-servlets-3/pom.xml index 2b4fc37fc4..8c339ce6d4 100644 --- a/javax-servlets-3/pom.xml +++ b/javax-servlets-3/pom.xml @@ -31,6 +31,7 @@ 5.1.3.RELEASE + uppercasing-app org.apache.maven.plugins diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java index 2c9f603d2c..61a7e896cc 100644 --- a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java +++ b/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java @@ -8,9 +8,8 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import java.io.IOException; -import java.io.PrintWriter; -@WebFilter(servletNames = { "uppercaseServlet" }, filterName = "emptyParamFilter") +@WebFilter(servletNames = { "uppercaseServlet" }, urlPatterns = "/uppercase") public class EmptyParamFilter implements Filter { @Override @@ -22,21 +21,13 @@ public class EmptyParamFilter implements Filter { FilterChain filterChain) throws IOException, ServletException { String inputString = servletRequest.getParameter("input"); - if (inputString == null || inputString.isEmpty()) { - response(servletResponse); - } else { + if (inputString != null && inputString.matches("[A-Za-z0-9]+")) { filterChain.doFilter(servletRequest, servletResponse); + } else { + servletResponse.getWriter().println("Missing input parameter"); } } - private void response(ServletResponse response) throws IOException { - response.setContentType("text/html"); - - PrintWriter out = response.getWriter(); - - out.println("Missing input parameter"); - } - @Override public void destroy() { } From ad3fe3d536b591014dc0e9d6dc07a11918abdbd4 Mon Sep 17 00:00:00 2001 From: Rodrigo Graciano Date: Fri, 15 Feb 2019 23:43:15 -0500 Subject: [PATCH 039/496] BAEL-2648 --- .../src/main/com/baeldung/range/CharRange.kt | 13 +++++++++ .../src/main/com/baeldung/range/Filter.kt | 18 ++++++++++++ .../src/main/com/baeldung/range/FirstLast.kt | 8 ++++++ .../com/baeldung/range/OtherRangeFunctions.kt | 14 ++++++++++ .../src/main/com/baeldung/range/Range.kt | 28 +++++++++++++++++++ .../main/com/baeldung/range/ReverseRange.kt | 14 ++++++++++ .../src/main/com/baeldung/range/Step.kt | 15 ++++++++++ .../src/main/com/baeldung/range/UntilRange.kt | 8 ++++++ 8 files changed, 118 insertions(+) create mode 100644 core-kotlin-2/src/main/com/baeldung/range/CharRange.kt create mode 100644 core-kotlin-2/src/main/com/baeldung/range/Filter.kt create mode 100644 core-kotlin-2/src/main/com/baeldung/range/FirstLast.kt create mode 100644 core-kotlin-2/src/main/com/baeldung/range/OtherRangeFunctions.kt create mode 100644 core-kotlin-2/src/main/com/baeldung/range/Range.kt create mode 100644 core-kotlin-2/src/main/com/baeldung/range/ReverseRange.kt create mode 100644 core-kotlin-2/src/main/com/baeldung/range/Step.kt create mode 100644 core-kotlin-2/src/main/com/baeldung/range/UntilRange.kt diff --git a/core-kotlin-2/src/main/com/baeldung/range/CharRange.kt b/core-kotlin-2/src/main/com/baeldung/range/CharRange.kt new file mode 100644 index 0000000000..3151674d61 --- /dev/null +++ b/core-kotlin-2/src/main/com/baeldung/range/CharRange.kt @@ -0,0 +1,13 @@ +package com.baeldung.range + +fun main(args: Array) { + + for (ch in 'a'..'f') { + print(ch) + } + println() + + for (ch in 'f' downTo 'a') { + print(ch) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/main/com/baeldung/range/Filter.kt b/core-kotlin-2/src/main/com/baeldung/range/Filter.kt new file mode 100644 index 0000000000..0e611b14cf --- /dev/null +++ b/core-kotlin-2/src/main/com/baeldung/range/Filter.kt @@ -0,0 +1,18 @@ +package com.baeldung.range + +fun main(args: Array) { + val r = 1..10 + + //Apply filter + val f = r.filter { it -> it % 2 == 0 } + println(f) + + //Map + val m = r.map { it -> it * it } + println(m) + + //Reduce + val rdc = r.reduce { a, b -> a + b } + println(rdc) + +} \ No newline at end of file diff --git a/core-kotlin-2/src/main/com/baeldung/range/FirstLast.kt b/core-kotlin-2/src/main/com/baeldung/range/FirstLast.kt new file mode 100644 index 0000000000..b82f5a8b9b --- /dev/null +++ b/core-kotlin-2/src/main/com/baeldung/range/FirstLast.kt @@ -0,0 +1,8 @@ +package com.baeldung.range + +fun main(args: Array) { + + println((1..9).first) + println((1..9 step 2).step) + println((3..9).reversed().last) +} \ No newline at end of file diff --git a/core-kotlin-2/src/main/com/baeldung/range/OtherRangeFunctions.kt b/core-kotlin-2/src/main/com/baeldung/range/OtherRangeFunctions.kt new file mode 100644 index 0000000000..19dcab89b2 --- /dev/null +++ b/core-kotlin-2/src/main/com/baeldung/range/OtherRangeFunctions.kt @@ -0,0 +1,14 @@ +package com.baeldung.range + +fun main(args: Array) { + + val r = 1..20 + println(r.min()) + println(r.max()) + println(r.sum()) + println(r.average()) + println(r.count()) + + val repeated = listOf(1, 1, 2, 4, 4, 6, 10) + println(repeated.distinct()) +} \ No newline at end of file diff --git a/core-kotlin-2/src/main/com/baeldung/range/Range.kt b/core-kotlin-2/src/main/com/baeldung/range/Range.kt new file mode 100644 index 0000000000..c313181599 --- /dev/null +++ b/core-kotlin-2/src/main/com/baeldung/range/Range.kt @@ -0,0 +1,28 @@ +package com.baeldung.range + +fun main(args: Array) { + + for (i in 1..9) { + print(i) + } + println() + + for (i in 9 downTo 1) { + print(i) + } + println() + + for (i in 1.rangeTo(9)) { + print(i) + } + println() + + for (i in 9.downTo(1)) { + print(i) + } + println() + + for (i in 1 until 9) { + print(i) + } +} diff --git a/core-kotlin-2/src/main/com/baeldung/range/ReverseRange.kt b/core-kotlin-2/src/main/com/baeldung/range/ReverseRange.kt new file mode 100644 index 0000000000..875cf62200 --- /dev/null +++ b/core-kotlin-2/src/main/com/baeldung/range/ReverseRange.kt @@ -0,0 +1,14 @@ +package com.baeldung.range + +fun main(args: Array) { + + (1..9).reversed().forEach { + print(it) + } + + println() + + (1..9).reversed().step(3).forEach { + print(it) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/main/com/baeldung/range/Step.kt b/core-kotlin-2/src/main/com/baeldung/range/Step.kt new file mode 100644 index 0000000000..b9c5d48588 --- /dev/null +++ b/core-kotlin-2/src/main/com/baeldung/range/Step.kt @@ -0,0 +1,15 @@ +package com.baeldung.range + +fun main(args: Array) { + + for(i in 1..9 step 2){ + print(i) + } + + println() + + for (i in 9 downTo 1 step 2){ + print(i) + } + +} \ No newline at end of file diff --git a/core-kotlin-2/src/main/com/baeldung/range/UntilRange.kt b/core-kotlin-2/src/main/com/baeldung/range/UntilRange.kt new file mode 100644 index 0000000000..2c116a286f --- /dev/null +++ b/core-kotlin-2/src/main/com/baeldung/range/UntilRange.kt @@ -0,0 +1,8 @@ +package com.baeldung.range + +fun main(args: Array) { + + for (i in 1 until 9) { + print(i) + } +} \ No newline at end of file From 36535a0585f1c1bcafb377b4d3e7f3e97c190a69 Mon Sep 17 00:00:00 2001 From: Krzysztof Majewski Date: Sat, 16 Feb 2019 14:49:48 +0100 Subject: [PATCH 040/496] BAEL-2576 --- ...stAndPathVariableValidationController.java | 31 +++++++++++++++ ...leValidationControllerIntegrationTest.java | 38 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java create mode 100644 spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java new file mode 100644 index 0000000000..b77598c113 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java @@ -0,0 +1,31 @@ +package com.baeldung.spring.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.*; + +@Controller +@RequestMapping("/public/api/1") +@Validated +public class RequestAndPathVariableValidationController { + + @GetMapping("/name-for-day") + public String getNameOfDayByNumberRequestParam(@RequestParam @Min(1) @Max(7) Integer dayOfWeek) { + return dayOfWeek + ""; + } + + @GetMapping("/name-for-day/{dayOfWeek}") + public String getNameOfDayByPathVariable(@PathVariable("dayOfWeek") @Min(1) @Max(7) Integer dayOfWeek) { + return dayOfWeek + ""; + } + + @GetMapping("/valid-name") + public void validStringRequestParam(@RequestParam @NotBlank @Size(max = 10) @Pattern(regexp = "^[A-Z][a-zA-Z0-9]+$") String name) { + + } + +} diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java new file mode 100644 index 0000000000..bd8c4ba419 --- /dev/null +++ b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java @@ -0,0 +1,38 @@ +package com.baeldung.spring.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.sampleapp.config.WebConfig; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = WebConfig.class) +@WebAppConfiguration +public class RequestAndPathVariableValidationControllerIntegrationTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext webApplicationContext; + + @Before + public void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + } + + @Test + public void getNameOfDayByNumberRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))).andExpect(status().isOk()); + } +} From 76339ca52eb0b8fe960b2221ade08d3efcd83735 Mon Sep 17 00:00:00 2001 From: Krzysztof Majewski Date: Sat, 16 Feb 2019 14:57:10 +0100 Subject: [PATCH 041/496] fix in test --- ...estAndPathVariableValidationControllerIntegrationTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java index bd8c4ba419..4b0880ac48 100644 --- a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java +++ b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java @@ -11,13 +11,13 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import com.baeldung.sampleapp.config.WebConfig; +import com.baeldung.spring.ClientWebConfig; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = WebConfig.class) +@ContextConfiguration(classes = ClientWebConfig.class) @WebAppConfiguration public class RequestAndPathVariableValidationControllerIntegrationTest { From 47fee6d00624151302a046dc71cd699ba7fa5d01 Mon Sep 17 00:00:00 2001 From: Krzysztof Majewski Date: Sat, 16 Feb 2019 15:01:11 +0100 Subject: [PATCH 042/496] test check --- ...stAndPathVariableValidationControllerIntegrationTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java index 4b0880ac48..68d2b71624 100644 --- a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java +++ b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java @@ -35,4 +35,9 @@ public class RequestAndPathVariableValidationControllerIntegrationTest { public void getNameOfDayByNumberRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))).andExpect(status().isOk()); } + + @Test + public void getNameOfDayByNumberRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))).andExpect(status().isBadRequest()); + } } From cbff011de430cf0df5970ed967ab0912706c6ccf Mon Sep 17 00:00:00 2001 From: Krzysztof Majewski Date: Sat, 16 Feb 2019 15:04:21 +0100 Subject: [PATCH 043/496] test check --- ...questAndPathVariableValidationControllerIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java index 68d2b71624..95507a61e8 100644 --- a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java +++ b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java @@ -37,7 +37,7 @@ public class RequestAndPathVariableValidationControllerIntegrationTest { } @Test - public void getNameOfDayByNumberRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { + public void getNameOfDayByNumberRequestParam_whenGetWithInvalidRequestParam_thenReturn400() throws Exception { mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))).andExpect(status().isBadRequest()); } } From ab081d7d969dad51f0ce4270c3e7f1fa9f437b5d Mon Sep 17 00:00:00 2001 From: Krzysztof Majewski Date: Sat, 16 Feb 2019 15:14:05 +0100 Subject: [PATCH 044/496] add more tests --- ...leValidationControllerIntegrationTest.java | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java index 95507a61e8..318a15d8f7 100644 --- a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java +++ b/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java @@ -33,11 +33,40 @@ public class RequestAndPathVariableValidationControllerIntegrationTest { @Test public void getNameOfDayByNumberRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { - mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))).andExpect(status().isOk()); + mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))) + .andExpect(status().isOk()); } @Test - public void getNameOfDayByNumberRequestParam_whenGetWithInvalidRequestParam_thenReturn400() throws Exception { - mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5))).andExpect(status().isBadRequest()); + public void getNameOfDayByNumberRequestParam_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(15))) + .andExpect(status().isBadRequest()); + } + + @Test + public void getNameOfDayByPathVariable_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day/{dayOfWeek}", Integer.toString(5))).andExpect(status().isOk()); + } + + @Test + public void getNameOfDayByPathVariable_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/name-for-day/{dayOfWeek}", Integer.toString(15))) + .andExpect(status().isBadRequest()); + } + + @Test + public void validStringRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception { + mockMvc.perform(get("/public/api/1/valid-name").param("name", "John")).andExpect(status().isOk()); + } + + @Test + public void validStringRequestParam_whenGetWithTooLongRequestParam_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/valid-name").param("name", "asdfghjklqw")) + .andExpect(status().isBadRequest()); + } + + @Test + public void validStringRequestParam_whenGetWithLowerCaseRequestParam_thenReturn400() throws Exception { + mockMvc.perform(get("/public/api/1/valid-name").param("name", "john")).andExpect(status().isBadRequest()); } } From 2a9cfa8f25cb98b975bad02448d3099bbc48d149 Mon Sep 17 00:00:00 2001 From: clininger Date: Sun, 17 Feb 2019 09:43:12 +0700 Subject: [PATCH 045/496] BAEL-2731 - reformatted Postman file --- .../foo_API_test.postman_collection.json | 364 +++++++++--------- 1 file changed, 182 insertions(+), 182 deletions(-) diff --git a/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json b/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json index cd9454c218..5a6230bd22 100644 --- a/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json +++ b/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json @@ -1,184 +1,184 @@ { - "info": { - "_postman_id": "9989b5be-13ba-4d22-8e43-d05dbf628e58", - "name": "foo API test", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - }, - "item": [ - { - "name": "add a foo", - "event": [ - { - "listen": "test", - "script": { - "id": "a01534dc-6fc7-4c54-ba1d-6bcf311e5836", - "exec": [ - "pm.test(\"success status\", () => pm.response.to.be.success );", - "", - "pm.test(\"name is correct\", () => ", - " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", - "", - "pm.test(\"id was assigned\", () => ", - " pm.expect(pm.response.json().id).to.be.not.null );", - "", - "pm.variables.set(\"id\", pm.response.json().id);" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "name": "Content-Type", - "value": "application/json", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"name\": \"Transformers\"\n}" - }, - "url": { - "raw": "http://localhost:8082/spring-boot-rest/auth/foos", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8082", - "path": [ - "spring-boot-rest", - "auth", - "foos" - ] - } - }, - "response": [] - }, - { - "name": "get a foo", - "event": [ - { - "listen": "test", - "script": { - "id": "03de440c-b483-4ab8-a11a-d0c99b349963", - "exec": [ - "pm.test(\"success status\", () => pm.response.to.be.success );", - "", - "pm.test(\"name is correct\", () => ", - " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", - "", - "pm.test(\"id is correct\", () => ", - " pm.expect(pm.response.json().id).to.equal(pm.variables.get(\"id\")) );" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8082", - "path": [ - "spring-boot-rest", - "auth", - "foos", - "{{id}}" - ] - } - }, - "response": [] - }, - { - "name": "delete a foo", - "event": [ - { - "listen": "test", - "script": { - "id": "74c1bb0f-c06c-48b1-a545-459233541b14", - "exec": [ - "pm.test(\"success status\", () => pm.response.to.be.success );" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "DELETE", - "header": [], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8082", - "path": [ - "spring-boot-rest", - "auth", - "foos", - "{{id}}" - ] - } - }, - "response": [] - }, - { - "name": "verify delete", - "event": [ - { - "listen": "test", - "script": { - "id": "03de440c-b483-4ab8-a11a-d0c99b349963", - "exec": [ - "pm.test(\"status is 500\", () => pm.response.to.have.status(500) );", - "", - "pm.test(\"no value present\", () => ", - " pm.expect(pm.response.json().cause).to.equal(\"No value present\"));" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "" - }, - "url": { - "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8082", - "path": [ - "spring-boot-rest", - "auth", - "foos", - "{{id}}" - ] - } - }, - "response": [] - } - ] + "info": { + "_postman_id": "9989b5be-13ba-4d22-8e43-d05dbf628e58", + "name": "foo API test", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "add a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "a01534dc-6fc7-4c54-ba1d-6bcf311e5836", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );", + "", + "pm.test(\"name is correct\", () => ", + " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", + "", + "pm.test(\"id was assigned\", () => ", + " pm.expect(pm.response.json().id).to.be.not.null );", + "", + "pm.variables.set(\"id\", pm.response.json().id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "name": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Transformers\"\n}" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos" + ] + } + }, + "response": [] + }, + { + "name": "get a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "03de440c-b483-4ab8-a11a-d0c99b349963", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );", + "", + "pm.test(\"name is correct\", () => ", + " pm.expect(pm.response.json().name).to.equal(\"Transformers\"));", + "", + "pm.test(\"id is correct\", () => ", + " pm.expect(pm.response.json().id).to.equal(pm.variables.get(\"id\")) );" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "delete a foo", + "event": [ + { + "listen": "test", + "script": { + "id": "74c1bb0f-c06c-48b1-a545-459233541b14", + "exec": [ + "pm.test(\"success status\", () => pm.response.to.be.success );" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + }, + { + "name": "verify delete", + "event": [ + { + "listen": "test", + "script": { + "id": "03de440c-b483-4ab8-a11a-d0c99b349963", + "exec": [ + "pm.test(\"status is 500\", () => pm.response.to.have.status(500) );", + "", + "pm.test(\"no value present\", () => ", + " pm.expect(pm.response.json().cause).to.equal(\"No value present\"));" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8082", + "path": [ + "spring-boot-rest", + "auth", + "foos", + "{{id}}" + ] + } + }, + "response": [] + } + ] } \ No newline at end of file From 79becf29d5a37f79b2d50b061bec34dfeefc642d Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 17 Feb 2019 16:32:35 +0530 Subject: [PATCH 046/496] [BAEL-12667] - Fixed the relative paths of parent --- spring-boot-crud/pom.xml | 21 ++++++++++--------- .../disabling-console-jul/pom.xml | 9 ++++---- .../disabling-console-log4j2/pom.xml | 9 ++++---- spring-boot-logging-log4j2/pom.xml | 7 ++++--- spring-soap/pom.xml | 8 ++++--- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/spring-boot-crud/pom.xml b/spring-boot-crud/pom.xml index 749bf9cb5a..73635b0a1c 100644 --- a/spring-boot-crud/pom.xml +++ b/spring-boot-crud/pom.xml @@ -3,15 +3,14 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 - com.baeldung.spring-boot-crud spring-boot-crud - 0.1.0 spring-boot-crud - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 @@ -41,11 +40,7 @@ h2 runtime - - - UTF-8 - 1.8 - + spring-boot-crud @@ -62,4 +57,10 @@ + + + UTF-8 + 1.8 + + \ No newline at end of file diff --git a/spring-boot-disable-console-logging/disabling-console-jul/pom.xml b/spring-boot-disable-console-logging/disabling-console-jul/pom.xml index 9ccbd56231..b95f610028 100644 --- a/spring-boot-disable-console-logging/disabling-console-jul/pom.xml +++ b/spring-boot-disable-console-logging/disabling-console-jul/pom.xml @@ -6,10 +6,11 @@ - org.springframework.boot - spring-boot-starter-parent - 2.1.1.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + diff --git a/spring-boot-disable-console-logging/disabling-console-log4j2/pom.xml b/spring-boot-disable-console-logging/disabling-console-log4j2/pom.xml index 0b360bb366..7db6c4ac1e 100644 --- a/spring-boot-disable-console-logging/disabling-console-log4j2/pom.xml +++ b/spring-boot-disable-console-logging/disabling-console-log4j2/pom.xml @@ -6,10 +6,11 @@ - org.springframework.boot - spring-boot-starter-parent - 2.1.1.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + diff --git a/spring-boot-logging-log4j2/pom.xml b/spring-boot-logging-log4j2/pom.xml index 6cc60da52c..b740585574 100644 --- a/spring-boot-logging-log4j2/pom.xml +++ b/spring-boot-logging-log4j2/pom.xml @@ -10,9 +10,10 @@ - spring-boot-starter-parent - org.springframework.boot - 2.0.5.RELEASE + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 diff --git a/spring-soap/pom.xml b/spring-soap/pom.xml index 2865a4c3bc..f5c3a1434d 100644 --- a/spring-soap/pom.xml +++ b/spring-soap/pom.xml @@ -8,13 +8,15 @@ 1.0.0 - org.springframework.boot - spring-boot-starter-parent - 2.1.2.RELEASE + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 1.8 + 2.1.2.RELEASE From 099a8c9ae7a14926de07a2221facae6b58b0e837 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Sun, 17 Feb 2019 17:07:18 +0100 Subject: [PATCH 047/496] [BAEL-2538] Updated to return int with @Modifying queries --- .../com/baeldung/dao/repositories/user/UserRepository.java | 4 ++-- .../dao/repositories/user/UserRepositoryIntegrationTest.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java index 366a784fe4..ad3b207fc6 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java @@ -79,8 +79,8 @@ public interface UserRepository extends JpaRepository , UserRepos void deactivateUsersNotLoggedInSince(@Param("date") LocalDate date); @Modifying(clearAutomatically = true, flushAutomatically = true) - @Query("delete User u where u.active = false") - void deleteDeactivatedUsers(); + @Query("delete from User u where u.active = false") + int deleteDeactivatedUsers(); @Modifying(clearAutomatically = true, flushAutomatically = true) @Query(value = "alter table USERS.USERS add column deleted int(1) not null default 0", nativeQuery = true) diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/user/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/user/UserRepositoryIntegrationTest.java index d57b5d16d0..14c2b0eb46 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/user/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/user/UserRepositoryIntegrationTest.java @@ -501,11 +501,12 @@ public class UserRepositoryIntegrationTest { userRepository.save(usr01); userRepository.save(usr02); - userRepository.deleteDeactivatedUsers(); + int deletedUsersCount = userRepository.deleteDeactivatedUsers(); List users = userRepository.findAll(); assertEquals(1, users.size()); assertEquals(usr01, users.get(0)); + assertEquals(1, deletedUsersCount); } @Test From 0da5c1117805a2c219d4840e17a119ab17c85e5a Mon Sep 17 00:00:00 2001 From: pcoates Date: Sun, 17 Feb 2019 16:54:40 +0000 Subject: [PATCH 048/496] BAEL-2492 Scenarios with WireMock --- testing-modules/rest-testing/pom.xml | 2 +- .../scenario/WireMockScenarioExampleTest.java | 77 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleTest.java diff --git a/testing-modules/rest-testing/pom.xml b/testing-modules/rest-testing/pom.xml index 2b1f146f0f..c3a9477a47 100644 --- a/testing-modules/rest-testing/pom.xml +++ b/testing-modules/rest-testing/pom.xml @@ -159,7 +159,7 @@ 2.9.0 1.2.5 - 2.4.1 + 2.21.0 0.6.1 4.4.5 diff --git a/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleTest.java b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleTest.java new file mode 100644 index 0000000000..b4e7393045 --- /dev/null +++ b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/wiremock/scenario/WireMockScenarioExampleTest.java @@ -0,0 +1,77 @@ +package com.baeldung.rest.wiremock.scenario; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.util.Scanner; + +import org.apache.http.HttpResponse; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.junit.Rule; +import org.junit.Test; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.stubbing.Scenario; + +public class WireMockScenarioExampleTest { + private static final String THIRD_STATE = "third"; + private static final String SECOND_STATE = "second"; + private static final String TIP_01 = "finally block is not called when System.exit() is called in the try block"; + private static final String TIP_02 = "keep your code clean"; + private static final String TIP_03 = "use composition rather than inheritance"; + private static final String TEXT_PLAIN = "text/plain"; + + static int port = 9999; + + @Rule + public WireMockRule wireMockRule = new WireMockRule(port); + + @Test + public void changeStateOnEachCallTest() throws IOException { + createWireMockStub(Scenario.STARTED, SECOND_STATE, TIP_01); + createWireMockStub(SECOND_STATE, THIRD_STATE, TIP_02); + createWireMockStub(THIRD_STATE, Scenario.STARTED, TIP_03); + + assertEquals(TIP_01, nextTip()); + assertEquals(TIP_02, nextTip()); + assertEquals(TIP_03, nextTip()); + assertEquals(TIP_01, nextTip()); + } + + private void createWireMockStub(String currentState, String nextState, String responseBody) { + stubFor(get(urlEqualTo("/java-tip")) + .inScenario("java tips") + .whenScenarioStateIs(currentState) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", TEXT_PLAIN) + .withBody(responseBody)) + .willSetStateTo(nextState) + ); + } + + private String nextTip() throws ClientProtocolException, IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpGet request = new HttpGet(String.format("http://localhost:%s/java-tip", port)); + HttpResponse httpResponse = httpClient.execute(request); + return firstLineOfResponse(httpResponse); + } + + private static String firstLineOfResponse(HttpResponse httpResponse) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()))) { + return reader.readLine(); + } + } + +} From 2252d72184fffc8f3430fdba4f914c04c0da0f50 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 17 Feb 2019 23:48:11 +0530 Subject: [PATCH 049/496] [BAEL-12669] - Check modules that don't use our standard parents --- ddd/pom.xml | 9 +++---- .../{OrderTest.java => OrderUnitTest.java} | 2 +- ...=> ViolateOrderBusinessRulesUnitTest.java} | 2 +- guest/remote-debugging/pom.xml | 9 +++---- guest/slf4j/guide/pom.xml | 8 ++++--- guest/spring-boot-app/pom.xml | 8 ++++--- ...t.java => EmployeeControllerUnitTest.java} | 2 +- guest/spring-mvc/pom.xml | 9 +++---- guest/spring-security/pom.xml | 9 +++---- guest/webservices/spring-rest-service/pom.xml | 8 ++++--- jta/pom.xml | 9 +++---- .../spring-boot-h2-database/pom.xml | 9 +++---- spring-5-reactive-oauth/pom.xml | 11 +++++---- spring-cloud/spring-cloud-functions/pom.xml | 24 ++++++++++--------- ... => CloudFunctionApplicationUnitTest.java} | 2 +- .../liveness-example/pom.xml | 9 +++---- .../readiness-example/pom.xml | 9 +++---- spring-cloud/spring-cloud-zuul/pom.xml | 11 +++++---- ...t.java => GreetingControllerUnitTest.java} | 2 +- 19 files changed, 85 insertions(+), 67 deletions(-) rename ddd/src/test/java/com/baeldung/ddd/order/{OrderTest.java => OrderUnitTest.java} (99%) rename ddd/src/test/java/com/baeldung/ddd/order/jpa/{ViolateOrderBusinessRulesTest.java => ViolateOrderBusinessRulesUnitTest.java} (96%) rename guest/spring-boot-app/src/test/java/com/stackify/test/{EmployeeControllerTest.java => EmployeeControllerUnitTest.java} (97%) rename spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/{CloudFunctionApplicationTests.java => CloudFunctionApplicationUnitTest.java} (96%) rename spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/{GreetingControllerTest.java => GreetingControllerUnitTest.java} (99%) diff --git a/ddd/pom.xml b/ddd/pom.xml index 749e444e52..4ac65ea841 100644 --- a/ddd/pom.xml +++ b/ddd/pom.xml @@ -9,10 +9,10 @@ DDD series examples - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 @@ -86,6 +86,7 @@ 1.0.1 2.22.0 + 2.0.6.RELEASE \ No newline at end of file diff --git a/ddd/src/test/java/com/baeldung/ddd/order/OrderTest.java b/ddd/src/test/java/com/baeldung/ddd/order/OrderUnitTest.java similarity index 99% rename from ddd/src/test/java/com/baeldung/ddd/order/OrderTest.java rename to ddd/src/test/java/com/baeldung/ddd/order/OrderUnitTest.java index 431a6a5293..502827960a 100644 --- a/ddd/src/test/java/com/baeldung/ddd/order/OrderTest.java +++ b/ddd/src/test/java/com/baeldung/ddd/order/OrderUnitTest.java @@ -11,7 +11,7 @@ import org.joda.money.Money; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -class OrderTest { +class OrderUnitTest { @DisplayName("given order with two items, when calculate total cost, then sum is returned") @Test void test0() throws Exception { diff --git a/ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesTest.java b/ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesUnitTest.java similarity index 96% rename from ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesTest.java rename to ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesUnitTest.java index 3eda9250f9..6f1de3276c 100644 --- a/ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesTest.java +++ b/ddd/src/test/java/com/baeldung/ddd/order/jpa/ViolateOrderBusinessRulesUnitTest.java @@ -7,7 +7,7 @@ import java.math.BigDecimal; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -public class ViolateOrderBusinessRulesTest { +public class ViolateOrderBusinessRulesUnitTest { @DisplayName("given two non-zero order line items, when create an order with them, it's possible to set total cost to zero") @Test void test() throws Exception { diff --git a/guest/remote-debugging/pom.xml b/guest/remote-debugging/pom.xml index 07b9cc49d8..5c6a2b3165 100644 --- a/guest/remote-debugging/pom.xml +++ b/guest/remote-debugging/pom.xml @@ -9,10 +9,10 @@ war - org.springframework.boot - spring-boot-starter-parent - 1.5.8.RELEASE - + parent-boot-1 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-1 @@ -39,6 +39,7 @@ UTF-8 UTF-8 + 1.5.8.RELEASE diff --git a/guest/slf4j/guide/pom.xml b/guest/slf4j/guide/pom.xml index 657ede73b6..b69efee32a 100644 --- a/guest/slf4j/guide/pom.xml +++ b/guest/slf4j/guide/pom.xml @@ -9,9 +9,10 @@ pom - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../../parent-boot-2 @@ -59,5 +60,6 @@ UTF-8 1.8 2.0.0-beta.5 + 2.0.6.RELEASE diff --git a/guest/spring-boot-app/pom.xml b/guest/spring-boot-app/pom.xml index 423dadbb99..ab3181b676 100644 --- a/guest/spring-boot-app/pom.xml +++ b/guest/spring-boot-app/pom.xml @@ -8,9 +8,10 @@ war - org.springframework.boot - spring-boot-starter-parent - 1.5.3.RELEASE + parent-boot-1 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-1 @@ -70,6 +71,7 @@ 8.0.43 UTF-8 1.8 + 1.5.3.RELEASE diff --git a/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerTest.java b/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerUnitTest.java similarity index 97% rename from guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerTest.java rename to guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerUnitTest.java index 2711a77ebd..9808546e82 100644 --- a/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerTest.java +++ b/guest/spring-boot-app/src/test/java/com/stackify/test/EmployeeControllerUnitTest.java @@ -21,7 +21,7 @@ import com.stackify.Application; @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) @WebAppConfiguration -public class EmployeeControllerTest { +public class EmployeeControllerUnitTest { private static final String CONTENT_TYPE = "application/json;charset=UTF-8"; diff --git a/guest/spring-mvc/pom.xml b/guest/spring-mvc/pom.xml index 3bffb1530d..b9d0899c77 100644 --- a/guest/spring-mvc/pom.xml +++ b/guest/spring-mvc/pom.xml @@ -10,10 +10,10 @@ Spring MVC sample project - org.springframework.boot - spring-boot-starter-parent - 2.0.0.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 @@ -30,6 +30,7 @@ UTF-8 UTF-8 + 2.0.0.RELEASE diff --git a/guest/spring-security/pom.xml b/guest/spring-security/pom.xml index 8be42ba32b..d38be54114 100644 --- a/guest/spring-security/pom.xml +++ b/guest/spring-security/pom.xml @@ -9,10 +9,10 @@ Spring Security Sample Project - org.springframework.boot - spring-boot-starter-parent - 2.0.0.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 @@ -48,6 +48,7 @@ UTF-8 UTF-8 3.0.8.RELEASE + 2.0.0.RELEASE \ No newline at end of file diff --git a/guest/webservices/spring-rest-service/pom.xml b/guest/webservices/spring-rest-service/pom.xml index fcec8a3e12..8849b82a3e 100644 --- a/guest/webservices/spring-rest-service/pom.xml +++ b/guest/webservices/spring-rest-service/pom.xml @@ -8,9 +8,10 @@ war - org.springframework.boot - spring-boot-starter-parent - 1.5.4.RELEASE + parent-boot-1 + com.baeldung + 0.0.1-SNAPSHOT + ../../../parent-boot-1 @@ -49,6 +50,7 @@ 1.8 2.7.0 2.7.0 + 1.5.4.RELEASE \ No newline at end of file diff --git a/jta/pom.xml b/jta/pom.xml index 038f1dc8d1..6a31733996 100644 --- a/jta/pom.xml +++ b/jta/pom.xml @@ -10,10 +10,10 @@ JEE JTA demo - org.springframework.boot - spring-boot-starter-parent - 2.0.4.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 @@ -85,5 +85,6 @@ UTF-8 1.8 2.4.1 + 2.0.4.RELEASE diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml b/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml index a181360e2b..882b88b535 100644 --- a/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml +++ b/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml @@ -11,10 +11,10 @@ Demo Spring Boot applications that starts H2 in memory database - org.springframework.boot - spring-boot-starter-parent - 2.0.4.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../../parent-boot-2 @@ -48,6 +48,7 @@ 1.8 com.baeldung.h2db.demo.server.SpringBootApp + 2.0.4.RELEASE diff --git a/spring-5-reactive-oauth/pom.xml b/spring-5-reactive-oauth/pom.xml index 86a5233ad4..ff076985e4 100644 --- a/spring-5-reactive-oauth/pom.xml +++ b/spring-5-reactive-oauth/pom.xml @@ -10,11 +10,11 @@ WebFluc and Spring Security OAuth - org.springframework.boot - spring-boot-starter-parent - 2.1.0.RELEASE - - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + @@ -70,6 +70,7 @@ UTF-8 UTF-8 1.8 + 2.1.0.RELEASE diff --git a/spring-cloud/spring-cloud-functions/pom.xml b/spring-cloud/spring-cloud-functions/pom.xml index 9396ad0a55..4d03e07e89 100644 --- a/spring-cloud/spring-cloud-functions/pom.xml +++ b/spring-cloud/spring-cloud-functions/pom.xml @@ -11,19 +11,12 @@ jar - org.springframework.boot - spring-boot-starter-parent - 2.0.4.RELEASE - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 - - UTF-8 - UTF-8 - 1.8 - 1.0.1.RELEASE - 2.0.2 - @@ -89,4 +82,13 @@ + + UTF-8 + UTF-8 + 1.8 + 1.0.1.RELEASE + 2.0.2 + 2.0.4.RELEASE + + diff --git a/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationTests.java b/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationUnitTest.java similarity index 96% rename from spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationTests.java rename to spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationUnitTest.java index 6039debe3f..e7b3fc8498 100644 --- a/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationTests.java +++ b/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/CloudFunctionApplicationUnitTest.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Java6Assertions.assertThat; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class CloudFunctionApplicationTests { +public class CloudFunctionApplicationUnitTest { @LocalServerPort private int port; diff --git a/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml index 9254718c81..b87f807391 100644 --- a/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml @@ -7,10 +7,10 @@ 1.0-SNAPSHOT - org.springframework.boot - spring-boot-starter-parent - 1.5.17.RELEASE - + parent-boot-1 + com.baeldung + 0.0.1-SNAPSHOT + ../../../parent-boot-1 @@ -44,6 +44,7 @@ UTF-8 UTF-8 1.8 + 1.5.17.RELEASE \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml index e22bb0a9fe..42fa10934b 100644 --- a/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml @@ -7,10 +7,10 @@ 1.0-SNAPSHOT - org.springframework.boot - spring-boot-starter-parent - 1.5.17.RELEASE - + parent-boot-1 + com.baeldung + 0.0.1-SNAPSHOT + ../../../parent-boot-1 @@ -44,6 +44,7 @@ UTF-8 UTF-8 1.8 + 1.5.17.RELEASE \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zuul/pom.xml b/spring-cloud/spring-cloud-zuul/pom.xml index 97e67f16d8..08990357d6 100644 --- a/spring-cloud/spring-cloud-zuul/pom.xml +++ b/spring-cloud/spring-cloud-zuul/pom.xml @@ -10,11 +10,11 @@ Demo project for Spring Boot - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE - - + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + @@ -72,6 +72,7 @@ UTF-8 1.8 Finchley.SR1 + 2.0.6.RELEASE diff --git a/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerTest.java b/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerUnitTest.java similarity index 99% rename from spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerTest.java rename to spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerUnitTest.java index d51f881112..d23ec836f9 100644 --- a/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerTest.java +++ b/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerUnitTest.java @@ -26,7 +26,7 @@ import org.springframework.test.context.junit4.SpringRunner; @AutoConfigureTestDatabase @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class GreetingControllerTest { +public class GreetingControllerUnitTest { private static final String SIMPLE_GREETING = "/greeting/simple"; private static final String ADVANCED_GREETING = "/greeting/advanced"; From 69ae99666ae1d2b8e1bab723c71a680d07e0fac4 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 17 Feb 2019 23:58:47 +0530 Subject: [PATCH 050/496] Reverted spring-boot-logging modules parents --- .../disabling-console-jul/pom.xml | 7 +++---- .../disabling-console-log4j2/pom.xml | 7 +++---- spring-boot-logging-log4j2/pom.xml | 7 +++---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/spring-boot-disable-console-logging/disabling-console-jul/pom.xml b/spring-boot-disable-console-logging/disabling-console-jul/pom.xml index b95f610028..f6f7890df1 100644 --- a/spring-boot-disable-console-logging/disabling-console-jul/pom.xml +++ b/spring-boot-disable-console-logging/disabling-console-jul/pom.xml @@ -6,10 +6,9 @@ - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../../parent-boot-2 + org.springframework.boot + spring-boot-starter-parent + 2.1.1.RELEASE diff --git a/spring-boot-disable-console-logging/disabling-console-log4j2/pom.xml b/spring-boot-disable-console-logging/disabling-console-log4j2/pom.xml index 7db6c4ac1e..1cf3eb3e68 100644 --- a/spring-boot-disable-console-logging/disabling-console-log4j2/pom.xml +++ b/spring-boot-disable-console-logging/disabling-console-log4j2/pom.xml @@ -6,10 +6,9 @@ - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../../parent-boot-2 + org.springframework.boot + spring-boot-starter-parent + 2.1.1.RELEASE diff --git a/spring-boot-logging-log4j2/pom.xml b/spring-boot-logging-log4j2/pom.xml index b740585574..6cc60da52c 100644 --- a/spring-boot-logging-log4j2/pom.xml +++ b/spring-boot-logging-log4j2/pom.xml @@ -10,10 +10,9 @@ - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../parent-boot-2 + spring-boot-starter-parent + org.springframework.boot + 2.0.5.RELEASE From 91028e62b2bf63afbe15609cff89eaed7015cf2d Mon Sep 17 00:00:00 2001 From: Muhammad Asif Anwar Date: Sun, 17 Feb 2019 23:01:46 +0400 Subject: [PATCH 051/496] for Jenkins --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1c016a2ea9..b4bab0a389 100644 --- a/pom.xml +++ b/pom.xml @@ -1594,7 +1594,7 @@ UTF-8 UTF-8 - refs/heads/master + refs/remotes/origin/master true false false From cc1183cd8336baa28c67019bbdb4f30b4ecc162e Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 17 Feb 2019 13:02:41 +0530 Subject: [PATCH 052/496] [BAEL-12668] - Make sure the tutorials build doesn't generate any un-committed or un-ignored artifacts --- .gitignore | 7 +++++++ .../java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java | 7 ++++--- core-java-io/src/test/resources/exampleOutput.csv | 2 -- persistence-modules/hibernate5/transaction.log | 0 4 files changed, 11 insertions(+), 5 deletions(-) delete mode 100644 core-java-io/src/test/resources/exampleOutput.csv delete mode 100644 persistence-modules/hibernate5/transaction.log diff --git a/.gitignore b/.gitignore index 0e71421ee7..21586748b7 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,10 @@ jmeter/src/main/resources/*-JMeter.csv **/nb-configuration.xml core-scala/.cache-main core-scala/.cache-tests + + +persistence-modules/hibernate5/transaction.log +apache-avro/src/main/java/com/baeldung/avro/model/ +jta/transaction-logs/ +software-security/sql-injection-samples/derby.log +spring-soap/src/main/java/com/baeldung/springsoap/gen/ \ No newline at end of file diff --git a/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java index 0658ec6101..5f4827bc21 100644 --- a/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java +++ b/core-java-io/src/test/java/com/baeldung/csv/WriteCsvFileExampleUnitTest.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -17,7 +18,6 @@ import org.slf4j.LoggerFactory; public class WriteCsvFileExampleUnitTest { private static final Logger LOG = LoggerFactory.getLogger(WriteCsvFileExampleUnitTest.class); - private static final String CSV_FILE_NAME = "src/test/resources/exampleOutput.csv"; private WriteCsvFileExample csvExample; @Before @@ -65,12 +65,12 @@ public class WriteCsvFileExampleUnitTest { } @Test - public void givenDataArray_whenConvertToCSV_thenOutputCreated() { + public void givenDataArray_whenConvertToCSV_thenOutputCreated() throws IOException { List dataLines = new ArrayList(); dataLines.add(new String[] { "John", "Doe", "38", "Comment Data\nAnother line of comment data" }); dataLines.add(new String[] { "Jane", "Doe, Jr.", "19", "She said \"I'm being quoted\"" }); - File csvOutputFile = new File(CSV_FILE_NAME); + File csvOutputFile = File.createTempFile("exampleOutput", ".csv"); try (PrintWriter pw = new PrintWriter(csvOutputFile)) { dataLines.stream() .map(csvExample::convertToCSV) @@ -80,5 +80,6 @@ public class WriteCsvFileExampleUnitTest { } assertTrue(csvOutputFile.exists()); + csvOutputFile.deleteOnExit(); } } diff --git a/core-java-io/src/test/resources/exampleOutput.csv b/core-java-io/src/test/resources/exampleOutput.csv deleted file mode 100644 index 45c37f3a3b..0000000000 --- a/core-java-io/src/test/resources/exampleOutput.csv +++ /dev/null @@ -1,2 +0,0 @@ -John,Doe,38,Comment Data Another line of comment data -Jane,"Doe, Jr.",19,"She said ""I'm being quoted""" \ No newline at end of file diff --git a/persistence-modules/hibernate5/transaction.log b/persistence-modules/hibernate5/transaction.log deleted file mode 100644 index e69de29bb2..0000000000 From b9a25375d602fd0ab94ada7a1de1e794c5fb5510 Mon Sep 17 00:00:00 2001 From: Tom Hombergs Date: Sun, 17 Feb 2019 20:59:36 +0100 Subject: [PATCH 053/496] added link --- core-java-collections-list/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md index d1112047ba..3a4a7c69e8 100644 --- a/core-java-collections-list/README.md +++ b/core-java-collections-list/README.md @@ -27,3 +27,4 @@ - [Flattening Nested Collections in Java](http://www.baeldung.com/java-flatten-nested-collections) - [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection) - [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) +- [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal) From 1ebebc1fa3c3fd83b483308a110320c2532fa796 Mon Sep 17 00:00:00 2001 From: Tom Hombergs Date: Sun, 17 Feb 2019 21:02:48 +0100 Subject: [PATCH 054/496] added link --- spring-security-angular/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-security-angular/README.md b/spring-security-angular/README.md index 80312c4bab..49cd8dd62d 100644 --- a/spring-security-angular/README.md +++ b/spring-security-angular/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Spring Security Login Page with Angular](https://www.baeldung.com/spring-security-login-angular) +- [Fixing 401s with CORS Preflights and Spring Security](https://www.baeldung.com/spring-security-cors-preflight) From 6c237aaf3a009fc178aafb88967e2749bd2017b9 Mon Sep 17 00:00:00 2001 From: psevestre Date: Mon, 18 Feb 2019 02:39:25 -0300 Subject: [PATCH 055/496] [BAEL-1381] Add JPA Examples (#6369) * BAEL-1381 * [BAEL-1381] * [BAEL-1381] New module name * [BAEL-1381] software-security module * [BAEL-1381] Add JPA examples --- .../CustomBaeldungQueueUnitTest.java | 0 .../PriorityQueueUnitTest.java | 0 .../sql-injection-samples/pom.xml | 15 +- .../examples/security/sql/Account.java | 34 ++++ .../examples/security/sql/AccountDAO.java | 171 +++++++++++++++--- .../src/main/resources/application.properties | 1 + .../resources/db/changelog/create-tables.xml | 19 -- .../main/resources/db/master-changelog.xml | 8 - ...qlInjectionSamplesApplicationUnitTest.java | 34 +++- .../src/test/resources/application-test.yml | 14 +- .../src/test/resources/schema.sql | 1 + 11 files changed, 246 insertions(+), 51 deletions(-) rename core-java-collections/src/test/java/com/baeldung/{queueinterface => queueInterface}/CustomBaeldungQueueUnitTest.java (100%) rename core-java-collections/src/test/java/com/baeldung/{queueinterface => queueInterface}/PriorityQueueUnitTest.java (100%) create mode 100644 software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java delete mode 100644 software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml delete mode 100644 software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml diff --git a/core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java b/core-java-collections/src/test/java/com/baeldung/queueInterface/CustomBaeldungQueueUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/queueinterface/CustomBaeldungQueueUnitTest.java rename to core-java-collections/src/test/java/com/baeldung/queueInterface/CustomBaeldungQueueUnitTest.java diff --git a/core-java-collections/src/test/java/com/baeldung/queueinterface/PriorityQueueUnitTest.java b/core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java similarity index 100% rename from core-java-collections/src/test/java/com/baeldung/queueinterface/PriorityQueueUnitTest.java rename to core-java-collections/src/test/java/com/baeldung/queueInterface/PriorityQueueUnitTest.java diff --git a/software-security/sql-injection-samples/pom.xml b/software-security/sql-injection-samples/pom.xml index e1590662b7..5b33c674d4 100644 --- a/software-security/sql-injection-samples/pom.xml +++ b/software-security/sql-injection-samples/pom.xml @@ -16,6 +16,8 @@ + + org.springframework.boot spring-boot-starter-jdbc @@ -42,6 +44,17 @@ provided + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.hibernate + hibernate-jpamodelgen + + + @@ -57,4 +70,4 @@ 1.8 - + \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java new file mode 100644 index 0000000000..3f077d5592 --- /dev/null +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/Account.java @@ -0,0 +1,34 @@ +/** + * + */ +package com.baeldung.examples.security.sql; + +import java.math.BigDecimal; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import lombok.Data; + +/** + * @author Philippe + * + */ +@Entity +@Table(name="Accounts") +@Data +public class Account { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + private Long id; + + private String customerId; + private String accNumber; + private String branchId; + private BigDecimal balance; + +} diff --git a/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java index 447dcc456d..c7285e5fd3 100644 --- a/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java +++ b/software-security/sql-injection-samples/src/main/java/com/baeldung/examples/security/sql/AccountDAO.java @@ -7,14 +7,24 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.persistence.EntityManager; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Root; +import javax.persistence.metamodel.SingularAttribute; import javax.sql.DataSource; import org.springframework.stereotype.Component; @@ -27,9 +37,11 @@ import org.springframework.stereotype.Component; public class AccountDAO { private final DataSource dataSource; + private final EntityManager em; - public AccountDAO(DataSource dataSource) { + public AccountDAO(DataSource dataSource, EntityManager em) { this.dataSource = dataSource; + this.em = em; } /** @@ -63,6 +75,26 @@ public class AccountDAO { } } + /** + * Return all accounts owned by a given customer,given his/her external id - JPA version + * + * @param customerId + * @return + */ + public List unsafeJpaFindAccountsByCustomerId(String customerId) { + String jql = "from Account where customerId = '" + customerId + "'"; + TypedQuery q = em.createQuery(jql, Account.class); + return q.getResultList() + .stream() + .map(a -> AccountDTO.builder() + .accNumber(a.getAccNumber()) + .balance(a.getBalance()) + .branchId(a.getAccNumber()) + .customerId(a.getCustomerId()) + .build()) + .collect(Collectors.toList()); + } + /** * Return all accounts owned by a given customer,given his/her external id * @@ -71,7 +103,7 @@ public class AccountDAO { */ public List safeFindAccountsByCustomerId(String customerId) { - String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = ?"; + String sql = "select customer_id, branch_id,acc_number,balance from Accounts where customer_id = ?"; try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement(sql)) { p.setString(1, customerId); @@ -93,23 +125,73 @@ public class AccountDAO { } } + /** + * Return all accounts owned by a given customer,given his/her external id - JPA version + * + * @param customerId + * @return + */ + public List safeJpaFindAccountsByCustomerId(String customerId) { + + String jql = "from Account where customerId = :customerId"; + TypedQuery q = em.createQuery(jql, Account.class) + .setParameter("customerId", customerId); + + return q.getResultList() + .stream() + .map(a -> AccountDTO.builder() + .accNumber(a.getAccNumber()) + .balance(a.getBalance()) + .branchId(a.getAccNumber()) + .customerId(a.getCustomerId()) + .build()) + .collect(Collectors.toList()); + } + + /** + * Return all accounts owned by a given customer,given his/her external id - JPA version + * + * @param customerId + * @return + */ + public List safeJpaCriteriaFindAccountsByCustomerId(String customerId) { + + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(Account.class); + Root root = cq.from(Account.class); + cq.select(root) + .where(cb.equal(root.get(Account_.customerId), customerId)); + + TypedQuery q = em.createQuery(cq); + + return q.getResultList() + .stream() + .map(a -> AccountDTO.builder() + .accNumber(a.getAccNumber()) + .balance(a.getBalance()) + .branchId(a.getAccNumber()) + .customerId(a.getCustomerId()) + .build()) + .collect(Collectors.toList()); + } + private static final Set VALID_COLUMNS_FOR_ORDER_BY = Stream.of("acc_number", "branch_id", "balance") .collect(Collectors.toCollection(HashSet::new)); + /** * Return all accounts owned by a given customer,given his/her external id * * @param customerId * @return */ - public List safeFindAccountsByCustomerId(String customerId, String orderBy) { + public List safeFindAccountsByCustomerId(String customerId, String orderBy) { String sql = "select " + "customer_id,acc_number,branch_id,balance from Accounts where customer_id = ? "; if (VALID_COLUMNS_FOR_ORDER_BY.contains(orderBy)) { sql = sql + " order by " + orderBy; - } - else { + } else { throw new IllegalArgumentException("Nice try!"); } @@ -135,35 +217,82 @@ public class AccountDAO { } } + + private static final Map> VALID_JPA_COLUMNS_FOR_ORDER_BY = Stream.of( + new AbstractMap.SimpleEntry<>(Account_.ACC_NUMBER, Account_.accNumber), + new AbstractMap.SimpleEntry<>(Account_.BRANCH_ID, Account_.branchId), + new AbstractMap.SimpleEntry<>(Account_.BALANCE, Account_.balance) + ) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + /** + * Return all accounts owned by a given customer,given his/her external id + * + * @param customerId + * @return + */ + public List safeJpaFindAccountsByCustomerId(String customerId, String orderBy) { + +SingularAttribute orderByAttribute = VALID_JPA_COLUMNS_FOR_ORDER_BY.get(orderBy); +if ( orderByAttribute == null) { + throw new IllegalArgumentException("Nice try!"); +} + +CriteriaBuilder cb = em.getCriteriaBuilder(); +CriteriaQuery cq = cb.createQuery(Account.class); +Root root = cq.from(Account.class); +cq.select(root) + .where(cb.equal(root.get(Account_.customerId), customerId)) + .orderBy(cb.asc(root.get(orderByAttribute))); + +TypedQuery q = em.createQuery(cq); + + return q.getResultList() + .stream() + .map(a -> AccountDTO.builder() + .accNumber(a.getAccNumber()) + .balance(a.getBalance()) + .branchId(a.getAccNumber()) + .customerId(a.getCustomerId()) + .build()) + .collect(Collectors.toList()); + + } + /** * Invalid placeholder usage example * * @param tableName * @return */ - public List wrongCountRecordsByTableName(String tableName) { + public Long wrongCountRecordsByTableName(String tableName) { + + try (Connection c = dataSource.getConnection(); PreparedStatement p = c.prepareStatement("select count(*) from ?")) { - try (Connection c = dataSource.getConnection(); - PreparedStatement p = c.prepareStatement("select count(*) from ?")) { - p.setString(1, tableName); ResultSet rs = p.executeQuery(); - List accounts = new ArrayList<>(); - while (rs.next()) { - AccountDTO acc = AccountDTO.builder() - .customerId(rs.getString("customerId")) - .branchId(rs.getString("branch_id")) - .accNumber(rs.getString("acc_number")) - .balance(rs.getBigDecimal("balance")) - .build(); + rs.next(); + return rs.getLong(1); - accounts.add(acc); - } - - return accounts; } catch (SQLException ex) { throw new RuntimeException(ex); } } + /** + * Invalid placeholder usage example - JPA + * + * @param tableName + * @return + */ + public Long wrongJpaCountRecordsByTableName(String tableName) { + + String jql = "select count(*) from :tableName"; + TypedQuery q = em.createQuery(jql, Long.class) + .setParameter("tableName", tableName); + + return q.getSingleResult(); + + } + } diff --git a/software-security/sql-injection-samples/src/main/resources/application.properties b/software-security/sql-injection-samples/src/main/resources/application.properties index e69de29bb2..8b13789179 100644 --- a/software-security/sql-injection-samples/src/main/resources/application.properties +++ b/software-security/sql-injection-samples/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml b/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml deleted file mode 100644 index a405c02049..0000000000 --- a/software-security/sql-injection-samples/src/main/resources/db/changelog/create-tables.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml b/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml deleted file mode 100644 index 047ca2b314..0000000000 --- a/software-security/sql-injection-samples/src/main/resources/db/master-changelog.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java b/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java index 1f37ba04b6..f61b738abc 100644 --- a/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java +++ b/software-security/sql-injection-samples/src/test/java/com/baeldung/examples/security/sql/SqlInjectionSamplesApplicationUnitTest.java @@ -40,6 +40,15 @@ public class SqlInjectionSamplesApplicationUnitTest { assertThat(accounts).hasSize(3); } + @Test + public void givenAVulnerableJpaMethod_whenHackedCustomerId_thenReturnAllAccounts() { + + List accounts = target.unsafeJpaFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isNotEmpty(); + assertThat(accounts).hasSize(3); + } + @Test public void givenASafeMethod_whenHackedCustomerId_thenReturnNoAccounts() { @@ -48,13 +57,36 @@ public class SqlInjectionSamplesApplicationUnitTest { assertThat(accounts).isEmpty(); } + @Test + public void givenASafeJpaMethod_whenHackedCustomerId_thenReturnNoAccounts() { + + List accounts = target.safeJpaFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isEmpty(); + } + + + @Test + public void givenASafeJpaCriteriaMethod_whenHackedCustomerId_thenReturnNoAccounts() { + + List accounts = target.safeJpaCriteriaFindAccountsByCustomerId("C1' or '1'='1"); + assertThat(accounts).isNotNull(); + assertThat(accounts).isEmpty(); + } + @Test(expected = IllegalArgumentException.class) public void givenASafeMethod_whenInvalidOrderBy_thenThroweException() { target.safeFindAccountsByCustomerId("C1", "INVALID"); } - @Test(expected = RuntimeException.class) + @Test(expected = Exception.class) public void givenWrongPlaceholderUsageMethod_whenNormalCall_thenThrowsException() { target.wrongCountRecordsByTableName("Accounts"); } + + @Test(expected = Exception.class) + public void givenWrongJpaPlaceholderUsageMethod_whenNormalCall_thenThrowsException() { + target.wrongJpaCountRecordsByTableName("Accounts"); + } + } diff --git a/software-security/sql-injection-samples/src/test/resources/application-test.yml b/software-security/sql-injection-samples/src/test/resources/application-test.yml index d07ee10aee..3af3f58bff 100644 --- a/software-security/sql-injection-samples/src/test/resources/application-test.yml +++ b/software-security/sql-injection-samples/src/test/resources/application-test.yml @@ -2,5 +2,17 @@ # Test profile configuration # spring: + liquibase: + change-log: db/changelog/db.changelog-master.xml + + jpa: + hibernate: + ddl-auto: none + datasource: - initialization-mode: always + initialization-mode: embedded + +logging: + level: + sql: DEBUG + \ No newline at end of file diff --git a/software-security/sql-injection-samples/src/test/resources/schema.sql b/software-security/sql-injection-samples/src/test/resources/schema.sql index bfb0ae8059..cfc4c44f98 100644 --- a/software-security/sql-injection-samples/src/test/resources/schema.sql +++ b/software-security/sql-injection-samples/src/test/resources/schema.sql @@ -1,4 +1,5 @@ create table Accounts ( + id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), customer_id varchar(16) not null, acc_number varchar(16) not null, branch_id decimal(8,0), From 96fbef6a14a945d23cb026bca75e219409c01530 Mon Sep 17 00:00:00 2001 From: anuraggoyal1 Date: Mon, 18 Feb 2019 21:14:38 +0530 Subject: [PATCH 056/496] changes as per review (#6341) * [BAEL-2471] Guide to Apache Commons MultiValuedMap * Update MultiValuedMapUnitTest.java * added empty lines * updated as per review comments * changes as per review --- .../baeldung/java/map/MultiValuedMapUnitTest.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java b/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java index b02b67f685..b3aaf8925f 100644 --- a/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java +++ b/java-collections-maps/src/test/java/com/baeldung/java/map/MultiValuedMapUnitTest.java @@ -9,8 +9,10 @@ import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.apache.commons.collections4.MultiMapUtils; +import org.apache.commons.collections4.MultiSet; import org.apache.commons.collections4.MultiValuedMap; import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.apache.commons.collections4.multimap.HashSetValuedHashMap; @@ -65,25 +67,28 @@ public class MultiValuedMapUnitTest { @Test public void givenMultiValuesMap_whenUsingKeysMethod_thenReturningAllKeys() { MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); map.put("fruits", "orange"); map.put("vehicles", "car"); map.put("vehicles", "bike"); - assertThat(((Collection) map.keys())).contains("fruits", "vehicles"); + MultiSet keys = map.keys(); + + assertThat((keys)).contains("fruits", "vehicles"); + } @Test public void givenMultiValuesMap_whenUsingKeySetMethod_thenReturningAllKeys() { MultiValuedMap map = new ArrayListValuedHashMap<>(); - map.put("fruits", "apple"); map.put("fruits", "orange"); map.put("vehicles", "car"); map.put("vehicles", "bike"); - assertThat((Collection) map.keySet()).contains("fruits", "vehicles"); + Set keys = map.keySet(); + + assertThat(keys).contains("fruits", "vehicles"); } From 243c671edbfc64c001ca3c25b9da6a9fddd85a0c Mon Sep 17 00:00:00 2001 From: FrancoCorleone Date: Mon, 18 Feb 2019 17:48:46 +0100 Subject: [PATCH 057/496] [BAEL-2566] Add example of Insert with Modifying Native Query (#6164) * [BAEL-2566] Add example of Insert with Modifying Native Query * [BAEL-2557] Fix MR conflicts * [BAEL-2557] Cleanup tests --- .../dao/repositories/user/UserRepository.java | 6 +++- .../repositories/UserRepositoryCommon.java | 30 +++++++++++++------ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java index 7d6b076517..fc6e72460a 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/user/UserRepository.java @@ -67,10 +67,14 @@ public interface UserRepository extends JpaRepository , UserRepos @Query(value = "UPDATE Users u SET u.status = ? WHERE u.name = ?", nativeQuery = true) int updateUserSetStatusForNameNative(Integer status, String name); + @Query(value = "INSERT INTO Users (name, age, email, status) VALUES (:name, :age, :email, :status)", nativeQuery = true) + @Modifying + void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("status") Integer status, @Param("email") String email); + @Modifying @Query(value = "UPDATE Users u SET status = ? WHERE u.name = ?", nativeQuery = true) int updateUserSetStatusForNameNativePostgres(Integer status, String name); @Query(value = "SELECT u FROM User u WHERE u.name IN :names") - List findUserByNameList(@Param("names") Collection names); + List findUserByNameList(@Param("names") Collection names); } diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryCommon.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryCommon.java index 55a453e48f..03cb20a858 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryCommon.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryCommon.java @@ -12,11 +12,7 @@ import org.springframework.data.jpa.domain.JpaSort; import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.transaction.annotation.Transactional; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; @@ -29,10 +25,10 @@ class UserRepositoryCommon { final String USER_EMAIL4 = "email4@example.com"; final Integer INACTIVE_STATUS = 0; final Integer ACTIVE_STATUS = 1; - private final String USER_EMAIL5 = "email5@example.com"; - private final String USER_EMAIL6 = "email6@example.com"; - private final String USER_NAME_ADAM = "Adam"; - private final String USER_NAME_PETER = "Peter"; + final String USER_EMAIL5 = "email5@example.com"; + final String USER_EMAIL6 = "email6@example.com"; + final String USER_NAME_ADAM = "Adam"; + final String USER_NAME_PETER = "Peter"; @Autowired protected UserRepository userRepository; @@ -384,6 +380,22 @@ class UserRepositoryCommon { assertThat(usersWithNames.size()).isEqualTo(2); } + + + @Test + @Transactional + public void whenInsertedWithQuery_ThenUserIsPersisted() { + userRepository.insertUser(USER_NAME_ADAM, 1, ACTIVE_STATUS, USER_EMAIL); + userRepository.insertUser(USER_NAME_PETER, 1, ACTIVE_STATUS, USER_EMAIL2); + + User userAdam = userRepository.findUserByNameLike(USER_NAME_ADAM); + User userPeter = userRepository.findUserByNameLike(USER_NAME_PETER); + + assertThat(userAdam).isNotNull(); + assertThat(userAdam.getEmail()).isEqualTo(USER_EMAIL); + assertThat(userPeter).isNotNull(); + assertThat(userPeter.getEmail()).isEqualTo(USER_EMAIL2); + } @After public void cleanUp() { From fe289003faf09e7468882a5a11aed33d694c5cac Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Mon, 18 Feb 2019 23:00:58 +0530 Subject: [PATCH 058/496] Added files for BAEL-2494 (#6370) --- .../com/baeldung/jackson/dtos/Address.java | 40 ++++++++++++ .../com/baeldung/jackson/dtos/Person.java | 51 +++++++++++++++ .../xml/XMLSerializeDeserializeUnitTest.java | 64 +++++++++++++++++-- .../src/test/resources/PersonGenerated.xml | 18 ++++++ jackson/src/test/resources/person.xml | 19 ++++++ 5 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 jackson/src/test/java/com/baeldung/jackson/dtos/Address.java create mode 100644 jackson/src/test/java/com/baeldung/jackson/dtos/Person.java create mode 100644 jackson/src/test/resources/PersonGenerated.xml create mode 100644 jackson/src/test/resources/person.xml diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java new file mode 100644 index 0000000000..19e7d4c53c --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java @@ -0,0 +1,40 @@ +package com.baeldung.jackson.dtos; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; + +public class Address { + + @JacksonXmlProperty(localName = "street_number") + String streetNumber; + + @JacksonXmlProperty(localName = "street_name") + String streetName; + + @JacksonXmlProperty(localName = "city") + String city; + + public String getStreetNumber() { + return streetNumber; + } + + public void setStreetNumber(String streetNumber) { + this.streetNumber = streetNumber; + } + + public String getStreetName() { + return streetName; + } + + public void setStreetName(String streetName) { + this.streetName = streetName; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java new file mode 100644 index 0000000000..7891595cc6 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java @@ -0,0 +1,51 @@ +package com.baeldung.jackson.dtos; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; +import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; + +@JacksonXmlRootElement(localName = "person") +public final class Person { + private String firstName; + private String lastName; + @JacksonXmlElementWrapper(useWrapping = false) + private List phoneNumbers = new ArrayList<>(); + @JacksonXmlElementWrapper(localName = "addresses") + private List
address = new ArrayList<>(); + + public List
getAddress() { + return address; + } + + public void setAddress(List
address) { + this.address = address; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + public List getPhoneNumbers() { + return phoneNumbers; + } + + public void setPhoneNumbers(List phoneNumbers) { + this.phoneNumbers = phoneNumbers; + } + + + +} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java index 0e2a52e75c..039edd45bc 100644 --- a/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java @@ -9,12 +9,16 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; import org.junit.Test; +import com.baeldung.jackson.dtos.Address; +import com.baeldung.jackson.dtos.Person; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.dataformat.xml.XmlMapper; -import com.fasterxml.jackson.annotation.JsonProperty; public class XMLSerializeDeserializeUnitTest { @@ -49,7 +53,7 @@ public class XMLSerializeDeserializeUnitTest { assertTrue(value.getX() == 1 && value.getY() == 2); } - @Test + @Test public void whenJavaGotFromXmlStrWithCapitalElem_thenCorrect() throws IOException { XmlMapper xmlMapper = new XmlMapper(); SimpleBeanForCapitalizedFields value = xmlMapper. @@ -67,6 +71,54 @@ public class XMLSerializeDeserializeUnitTest { assertNotNull(file); } + @Test + public void whenJavaDeserializedFromXmlFile_thenCorrect() throws IOException { + XmlMapper xmlMapper = new XmlMapper(); + Person value = xmlMapper.readValue(new File("src/test/resources/person.xml"), Person.class); + + assertTrue(value.getAddress() + .get(0) + .getCity() + .equalsIgnoreCase("city1") + && value.getAddress() + .get(1) + .getCity() + .equalsIgnoreCase("city2")); + } + + @Test + public void whenJavaSerializedToXmlFile_thenSuccess() throws IOException { + XmlMapper xmlMapper = new XmlMapper(); + + Person person = new Person(); + + person.setFirstName("Rohan"); + person.setLastName("Daye"); + + List ph = new ArrayList<>(); + ph.add("9911778981"); + ph.add("9991111111"); + person.setPhoneNumbers(ph); + + List
addresses = new ArrayList<>(); + + Address address1 = new Address(); + address1.setStreetNumber("1"); + address1.setStreetName("streetname1"); + address1.setCity("city1"); + + Address address2 = new Address(); + address2.setStreetNumber("2"); + address2.setStreetName("streetname2"); + address2.setCity("city2"); + + addresses.add(address1); + addresses.add(address2); + person.setAddress(addresses); + + xmlMapper.writeValue(new File("src/test/resources/PersonGenerated.xml"), person); + } + private static String inputStreamToString(InputStream is) throws IOException { BufferedReader br; StringBuilder sb = new StringBuilder(); @@ -103,10 +155,10 @@ class SimpleBean { } -class SimpleBeanForCapitalizedFields { - @JsonProperty("X") - private int x = 1; - private int y = 2; +class SimpleBeanForCapitalizedFields { + @JsonProperty("X") + private int x = 1; + private int y = 2; public int getX() { return x; diff --git a/jackson/src/test/resources/PersonGenerated.xml b/jackson/src/test/resources/PersonGenerated.xml new file mode 100644 index 0000000000..6ebadd971a --- /dev/null +++ b/jackson/src/test/resources/PersonGenerated.xml @@ -0,0 +1,18 @@ + + + + 9911778981 + 9991111111 + +
+ 1 + streetname1 + city1 +
+
+ 2 + streetname2 + city2 +
+
+
\ No newline at end of file diff --git a/jackson/src/test/resources/person.xml b/jackson/src/test/resources/person.xml new file mode 100644 index 0000000000..39a6e859c4 --- /dev/null +++ b/jackson/src/test/resources/person.xml @@ -0,0 +1,19 @@ + + + Rohan + Daye + 9911034731 + 9911033478 + +
+ 1 + Name1 + City1 +
+
+ 2 + Name2 + City2 +
+
+
\ No newline at end of file From 19b0b021024d0add9dda880d5be59ad72bc36ba6 Mon Sep 17 00:00:00 2001 From: Sushant Date: Mon, 18 Feb 2019 19:39:36 +0100 Subject: [PATCH 059/496] Change variable name --- .../stringcomparison/StringComparisonTest.kt | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt index 1ba98da8dd..9528f62df5 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt +++ b/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt @@ -6,42 +6,42 @@ import kotlin.test.assertTrue class StringComparisonUnitTest { - @Test - fun `compare using equals operator`() { - val first = "kotlin" - val second = "kotlin" - val firstCapitalized = "KOTLIN" - assertTrue { first == second } - assertFalse { first == firstCapitalized } - } + @Test + fun `compare using equals operator`() { + val first = "kotlin" + val second = "kotlin" + val firstCapitalized = "KOTLIN" + assertTrue { first == second } + assertFalse { first == firstCapitalized } + } - @Test - fun `compare using referential equals operator`() { - val first = "kotlin" - val second = "kotlin" - val firstBuildAgain = buildString { "kotlin" } - assertTrue { first === second } - assertFalse { first === firstBuildAgain } - } + @Test + fun `compare using referential equals operator`() { + val first = "kotlin" + val second = "kotlin" + val copyOfFirst = buildString { "kotlin" } + assertTrue { first === second } + assertFalse { first === copyOfFirst } + } - @Test - fun `compare using equals method`() { - val first = "kotlin" - val second = "kotlin" - val firstCapitalized = "KOTLIN" - assertTrue { first.equals(second) } - assertFalse { first.equals(firstCapitalized) } - assertTrue { first.equals(firstCapitalized, true) } - } + @Test + fun `compare using equals method`() { + val first = "kotlin" + val second = "kotlin" + val firstCapitalized = "KOTLIN" + assertTrue { first.equals(second) } + assertFalse { first.equals(firstCapitalized) } + assertTrue { first.equals(firstCapitalized, true) } + } - @Test - fun `compare using compare method`() { - val first = "kotlin" - val second = "kotlin" - val firstCapitalized = "KOTLIN" - assertTrue { first.compareTo(second) == 0 } - assertTrue { first.compareTo(firstCapitalized) == 32 } - assertTrue { firstCapitalized.compareTo(first) == -32 } - assertTrue { first.compareTo(firstCapitalized, true) == 0 } - } + @Test + fun `compare using compare method`() { + val first = "kotlin" + val second = "kotlin" + val firstCapitalized = "KOTLIN" + assertTrue { first.compareTo(second) == 0 } + assertTrue { first.compareTo(firstCapitalized) == 32 } + assertTrue { firstCapitalized.compareTo(first) == -32 } + assertTrue { first.compareTo(firstCapitalized, true) == 0 } + } } \ No newline at end of file From 3a31350123af836518ec958c0484c9590fc5957c Mon Sep 17 00:00:00 2001 From: Amy DeGregorio Date: Mon, 18 Feb 2019 13:52:57 -0500 Subject: [PATCH 060/496] BAEL-2663 iterating a map (#6334) * Examples for BAEL-2663 iterating a map * Update for BAEL-2663 to use index in example --- .../com/baeldung/map/MapUnitTest.groovy | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy diff --git a/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy new file mode 100644 index 0000000000..97ffc50c76 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy @@ -0,0 +1,85 @@ +package com.baeldung.map + +import static org.junit.Assert.* +import org.junit.Test + +class MapUnitTest { + + @Test + void whenUsingEach_thenMapIsIterated() { + def map = [ + 'FF0000' : 'Red', + '00FF00' : 'Lime', + '0000FF' : 'Blue', + 'FFFF00' : 'Yellow' + ] + + map.each { println "Hex Code: $it.key = Color Name: $it.value" } + } + + @Test + void whenUsingEachWithEntry_thenMapIsIterated() { + def map = [ + 'E6E6FA' : 'Lavender', + 'D8BFD8' : 'Thistle', + 'DDA0DD' : 'Plum', + ] + + map.each { entry -> println "Hex Code: $entry.key = Color Name: $entry.value" } + } + + @Test + void whenUsingEachWithKeyAndValue_thenMapIsIterated() { + def map = [ + '000000' : 'Black', + 'FFFFFF' : 'White', + '808080' : 'Gray' + ] + + map.each { key, val -> + println "Hex Code: $key = Color Name $val" + } + } + + @Test + void whenUsingEachWithIndexAndEntry_thenMapIsIterated() { + def map = [ + '800080' : 'Purple', + '4B0082' : 'Indigo', + '6A5ACD' : 'Slate Blue' + ] + + map.eachWithIndex { entry, index -> + def indent = ((index == 0 || index % 2 == 0) ? " " : "") + println "$indent Hex Code: $entry.key = Color Name: $entry.value" + } + } + + @Test + void whenUsingEachWithIndexAndKeyAndValue_thenMapIsIterated() { + def map = [ + 'FFA07A' : 'Light Salmon', + 'FF7F50' : 'Coral', + 'FF6347' : 'Tomato', + 'FF4500' : 'Orange Red' + ] + + map.eachWithIndex { key, val, index -> + def indent = ((index == 0 || index % 2 == 0) ? " " : "") + println "$indent Hex Code: $key = Color Name: $val" + } + } + + @Test + void whenUsingForLoop_thenMapIsIterated() { + def map = [ + '2E8B57' : 'Seagreen', + '228B22' : 'Forest Green', + '008000' : 'Green' + ] + + for (entry in map) { + println "Hex Code: $entry.key = Color Name: $entry.value" + } + } +} From bad8753fd17cad0f3474914435fc81ddba4f9e76 Mon Sep 17 00:00:00 2001 From: Rodrigo Graciano Date: Mon, 18 Feb 2019 22:41:01 -0500 Subject: [PATCH 061/496] BAEL-2648 --- core-kotlin-2/pom.xml | 64 ++++++++++++++++++- .../com/baeldung/range/CharRange.kt | 0 .../{ => kotlin}/com/baeldung/range/Filter.kt | 0 .../com/baeldung/range/FirstLast.kt | 0 .../com/baeldung/range/OtherRangeFunctions.kt | 0 .../{ => kotlin}/com/baeldung/range/Range.kt | 0 .../com/baeldung/range/ReverseRange.kt | 0 .../{ => kotlin}/com/baeldung/range/Step.kt | 0 .../com/baeldung/range/UntilRange.kt | 0 .../com/baeldung/range/CharRangeTest.kt | 17 +++++ .../kotlin/com/baeldung/range/FilterTest.kt | 24 +++++++ .../com/baeldung/range/FirstLastTest.kt | 22 +++++++ .../baeldung/range/OtherRangeFunctionsTest.kt | 40 ++++++++++++ .../kotlin/com/baeldung/range/RangeTest.kt | 22 +++++++ .../com/baeldung/range/ReverseRangeTest.kt | 12 ++++ .../kotlin/com/baeldung/range/StepTest.kt | 17 +++++ .../com/baeldung/range/UntilRangeTest.kt | 12 ++++ 17 files changed, 229 insertions(+), 1 deletion(-) rename core-kotlin-2/src/main/{ => kotlin}/com/baeldung/range/CharRange.kt (100%) rename core-kotlin-2/src/main/{ => kotlin}/com/baeldung/range/Filter.kt (100%) rename core-kotlin-2/src/main/{ => kotlin}/com/baeldung/range/FirstLast.kt (100%) rename core-kotlin-2/src/main/{ => kotlin}/com/baeldung/range/OtherRangeFunctions.kt (100%) rename core-kotlin-2/src/main/{ => kotlin}/com/baeldung/range/Range.kt (100%) rename core-kotlin-2/src/main/{ => kotlin}/com/baeldung/range/ReverseRange.kt (100%) rename core-kotlin-2/src/main/{ => kotlin}/com/baeldung/range/Step.kt (100%) rename core-kotlin-2/src/main/{ => kotlin}/com/baeldung/range/UntilRange.kt (100%) create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/CharRangeTest.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/FilterTest.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/FirstLastTest.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/OtherRangeFunctionsTest.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/RangeTest.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/ReverseRangeTest.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/StepTest.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/UntilRangeTest.kt diff --git a/core-kotlin-2/pom.xml b/core-kotlin-2/pom.xml index 81df3cee81..e329611593 100644 --- a/core-kotlin-2/pom.xml +++ b/core-kotlin-2/pom.xml @@ -13,4 +13,66 @@ ../parent-kotlin - + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.jetbrains.kotlin + kotlin-test + ${kotlin.version} + test + + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + 1.8 + + + + + + + 1.2.71 + 1.1.1 + 5.2.0 + 3.10.0 + + + \ No newline at end of file diff --git a/core-kotlin-2/src/main/com/baeldung/range/CharRange.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/CharRange.kt similarity index 100% rename from core-kotlin-2/src/main/com/baeldung/range/CharRange.kt rename to core-kotlin-2/src/main/kotlin/com/baeldung/range/CharRange.kt diff --git a/core-kotlin-2/src/main/com/baeldung/range/Filter.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/Filter.kt similarity index 100% rename from core-kotlin-2/src/main/com/baeldung/range/Filter.kt rename to core-kotlin-2/src/main/kotlin/com/baeldung/range/Filter.kt diff --git a/core-kotlin-2/src/main/com/baeldung/range/FirstLast.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/FirstLast.kt similarity index 100% rename from core-kotlin-2/src/main/com/baeldung/range/FirstLast.kt rename to core-kotlin-2/src/main/kotlin/com/baeldung/range/FirstLast.kt diff --git a/core-kotlin-2/src/main/com/baeldung/range/OtherRangeFunctions.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/OtherRangeFunctions.kt similarity index 100% rename from core-kotlin-2/src/main/com/baeldung/range/OtherRangeFunctions.kt rename to core-kotlin-2/src/main/kotlin/com/baeldung/range/OtherRangeFunctions.kt diff --git a/core-kotlin-2/src/main/com/baeldung/range/Range.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/Range.kt similarity index 100% rename from core-kotlin-2/src/main/com/baeldung/range/Range.kt rename to core-kotlin-2/src/main/kotlin/com/baeldung/range/Range.kt diff --git a/core-kotlin-2/src/main/com/baeldung/range/ReverseRange.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/ReverseRange.kt similarity index 100% rename from core-kotlin-2/src/main/com/baeldung/range/ReverseRange.kt rename to core-kotlin-2/src/main/kotlin/com/baeldung/range/ReverseRange.kt diff --git a/core-kotlin-2/src/main/com/baeldung/range/Step.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/Step.kt similarity index 100% rename from core-kotlin-2/src/main/com/baeldung/range/Step.kt rename to core-kotlin-2/src/main/kotlin/com/baeldung/range/Step.kt diff --git a/core-kotlin-2/src/main/com/baeldung/range/UntilRange.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/UntilRange.kt similarity index 100% rename from core-kotlin-2/src/main/com/baeldung/range/UntilRange.kt rename to core-kotlin-2/src/main/kotlin/com/baeldung/range/UntilRange.kt diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/CharRangeTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/CharRangeTest.kt new file mode 100644 index 0000000000..0e23f508b6 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/CharRangeTest.kt @@ -0,0 +1,17 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +class CharRangeTest { + + @Test + fun testCharRange() { + assertEquals(listOf('a', 'b', 'c'), ('a'..'c').toList()) + } + + @Test + fun testCharDownRange() { + assertEquals(listOf('c', 'b', 'a'), ('c'.downTo('a')).toList()) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/FilterTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/FilterTest.kt new file mode 100644 index 0000000000..d0e2df8860 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/FilterTest.kt @@ -0,0 +1,24 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +class FilterTest { + + val r = 1..10 + + @Test + fun filterTest() { + assertEquals(listOf(2, 4, 6, 8, 10), r.filter { it -> it % 2 == 0 }.toList()) + } + + @Test + fun mapTest() { + assertEquals(listOf(1, 4, 9, 16, 25, 36, 49, 64, 81, 100), r.map { it -> it * it }.toList()) + } + + @Test + fun reduceTest() { + assertEquals(55, r.reduce { a, b -> a + b }) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/FirstLastTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/FirstLastTest.kt new file mode 100644 index 0000000000..ca797e9c9b --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/FirstLastTest.kt @@ -0,0 +1,22 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +class FirstLastTest { + + @Test + fun testFirst() { + assertEquals(1, (1..9).first) + } + + @Test + fun testLast() { + assertEquals(9, (1..9).last) + } + + @Test + fun testStep() { + assertEquals(2, (1..9 step 2).step) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/OtherRangeFunctionsTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/OtherRangeFunctionsTest.kt new file mode 100644 index 0000000000..d2d36bbfae --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/OtherRangeFunctionsTest.kt @@ -0,0 +1,40 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +class OtherRangeFunctionsTest { + + val r = 1..20 + val repeated = listOf(1, 1, 2, 4, 4, 6, 10) + + @Test + fun testMin() { + assertEquals(1, r.min()) + } + + @Test + fun testMax() { + assertEquals(20, r.max()) + } + + @Test + fun testSum() { + assertEquals(210, r.sum()) + } + + @Test + fun testAverage() { + assertEquals(10.5, r.average()) + } + + @Test + fun testCount() { + assertEquals(20, r.count()) + } + + @Test + fun testDistinct() { + assertEquals(listOf(1, 2, 4, 6, 10), repeated.distinct()) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/RangeTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/RangeTest.kt new file mode 100644 index 0000000000..48fa483924 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/RangeTest.kt @@ -0,0 +1,22 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +class RangeTest { + + @Test + fun testRange() { + assertEquals(listOf(1,2,3), (1.rangeTo(3).toList())) + } + + @Test + fun testDownTo(){ + assertEquals(listOf(3,2,1), (3.downTo(1).toList())) + } + + @Test + fun testUntil(){ + assertEquals(listOf(1,2), (1.until(3).toList())) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/ReverseRangeTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/ReverseRangeTest.kt new file mode 100644 index 0000000000..7e1c7badb7 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/ReverseRangeTest.kt @@ -0,0 +1,12 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +class ReverseRangeTest { + + @Test + fun reversedTest() { + assertEquals(listOf(9, 6, 3), (1..9).reversed().step(3).toList()) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/StepTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/StepTest.kt new file mode 100644 index 0000000000..4570ceeb0a --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/StepTest.kt @@ -0,0 +1,17 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +class StepTest { + + @Test + fun testStep() { + assertEquals(listOf(1, 3, 5, 7, 9), (1..9 step 2).toList()) + } + + @Test + fun testStepDown() { + assertEquals(listOf(9, 7, 5, 3, 1), (9 downTo 1 step 2).toList()) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/UntilRangeTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/UntilRangeTest.kt new file mode 100644 index 0000000000..f941c7f1e6 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/UntilRangeTest.kt @@ -0,0 +1,12 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertEquals + +class UntilRangeTest { + + @Test + fun testUntil() { + assertEquals(listOf(1, 2, 3, 4), (1 until 5).toList()) + } +} \ No newline at end of file From 78d0b85b2dc69d132ec15b15007cd440ad5b9fab Mon Sep 17 00:00:00 2001 From: dupirefr Date: Tue, 19 Feb 2019 07:24:07 +0100 Subject: [PATCH 062/496] [BAEL-2538] Rearranged classes --- .../com/baeldung/util/LocalDateConverter.java | 25 ------------------- .../UserRepositoryIntegrationTest.java | 0 2 files changed, 25 deletions(-) delete mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java rename persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/{user => }/UserRepositoryIntegrationTest.java (100%) diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java deleted file mode 100644 index 00fd378b05..0000000000 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/util/LocalDateConverter.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.util; - -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; -import java.sql.Date; -import java.time.LocalDate; -import java.util.Optional; - -@Converter(autoApply = true) -public class LocalDateConverter implements AttributeConverter { - - @Override - public Date convertToDatabaseColumn(LocalDate localDate) { - return Optional.ofNullable(localDate) - .map(Date::valueOf) - .orElse(null); - } - - @Override - public LocalDate convertToEntityAttribute(Date date) { - return Optional.ofNullable(date) - .map(Date::toLocalDate) - .orElse(null); - } -} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/user/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java similarity index 100% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/user/UserRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/UserRepositoryIntegrationTest.java From 1f7bff62eb7f8239fd59835791c19c25a46e4832 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Tue, 19 Feb 2019 13:28:30 +0400 Subject: [PATCH 063/496] final sort tests --- .../java/sort/CollectionsSortCompare.java | 39 +++++++++++++++++++ .../performance/ArraySortBenchmark.java | 27 +++++-------- 2 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 core-java-collections/src/main/java/com/baeldung/java/sort/CollectionsSortCompare.java diff --git a/core-java-collections/src/main/java/com/baeldung/java/sort/CollectionsSortCompare.java b/core-java-collections/src/main/java/com/baeldung/java/sort/CollectionsSortCompare.java new file mode 100644 index 0000000000..1eff522877 --- /dev/null +++ b/core-java-collections/src/main/java/com/baeldung/java/sort/CollectionsSortCompare.java @@ -0,0 +1,39 @@ +package com.baeldung.java.sort; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class CollectionsSortCompare { + + public static void main(String[] args) { + sortPrimitives(); + sortReferenceType(); + sortCollection(); + } + + private static void sortReferenceType() { + Integer[] numbers = {5, 22, 10, 0}; + Arrays.sort(numbers); + System.out.println(Arrays.toString(numbers)); + } + + private static void sortCollection() { + List numbersList = new ArrayList<>(); + numbersList.add(5); + numbersList.add(22); + numbersList.add(10); + numbersList.add(0); + + Collections.sort(numbersList); + + numbersList.forEach(System.out::print); + } + + private static void sortPrimitives() { + int[] numbers = {5, 22, 10, 0}; + Arrays.sort(numbers); + System.out.println(Arrays.toString(numbers)); + } +} diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java index 14cef2406a..a1d40657d3 100644 --- a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java +++ b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java @@ -12,37 +12,30 @@ import java.util.List; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.SingleShotTime) -@OutputTimeUnit(TimeUnit.MINUTES) +@OutputTimeUnit(TimeUnit.MILLISECONDS) @Measurement(batchSize = 100000, iterations = 10) @Warmup(batchSize = 100000, iterations = 10) public class ArraySortBenchmark { @State(Scope.Thread) public static class Initialize { - - String[] words = {"Java", "Baeldung", "Tutorial"}; - List wordList = new ArrayList<>(); - - @Setup(Level.Trial) - public void setUp() { - wordList.add("Java"); - wordList.add("Baeldung"); - wordList.add("Tutorial"); - } + Integer[] numbers = {5, 22, 10, 0}; + int[] primitives = {5, 22, 10, 0}; } @Benchmark - public String[] benchmarkArraysSort(ArraySortBenchmark.Initialize state) { - Arrays.sort(state.words); - return state.words; + public Integer[] benchmarkArraysIntegerSort(ArraySortBenchmark.Initialize state) { + Arrays.sort(state.numbers); + return state.numbers; } @Benchmark - public List benchmarkCollectionsSort(ArraySortBenchmark.Initialize state) { - Collections.sort(state.wordList); - return state.wordList; + public int[] benchmarkArraysIntSort(ArraySortBenchmark.Initialize state) { + Arrays.sort(state.primitives); + return state.primitives; } + public static void main(String[] args) throws Exception { Options options = new OptionsBuilder() .include(ArraySortBenchmark.class.getSimpleName()).threads(1) From 50858001fff2dbdeee5e4626ea987e3124eebb6a Mon Sep 17 00:00:00 2001 From: mprevisic Date: Tue, 19 Feb 2019 14:17:32 +0100 Subject: [PATCH 064/496] [BAEL-2533] moved code examples to new module --- .../.mvn/wrapper/MavenWrapperDownloader.java | 114 +++++++ .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 48337 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 + spring-boot-data/README.md | 0 spring-boot-data/mvnw | 286 ++++++++++++++++++ spring-boot-data/mvnw.cmd | 161 ++++++++++ spring-boot-data/pom.xml | 122 ++++++++ .../baeldung/SpringBootDataApplication.java | 13 + .../com/baeldung/jsondateformat/Contact.java | 70 +++++ .../baeldung/jsondateformat/ContactApp.java | 13 + .../jsondateformat/ContactAppConfig.java | 33 ++ .../jsondateformat/ContactController.java | 77 +++++ .../ContactWithJavaUtilDate.java | 69 +++++ .../baeldung/jsondateformat/PlainContact.java | 66 ++++ .../PlainContactWithJavaUtilDate.java | 69 +++++ .../src/main/resources/application.properties | 2 + .../ContactAppIntegrationTest.java | 100 ++++++ ...ObjectMapperCustomizerIntegrationTest.java | 67 ++++ .../src/test/resources/application.properties | 0 19 files changed, 1263 insertions(+) create mode 100644 spring-boot-data/.mvn/wrapper/MavenWrapperDownloader.java create mode 100644 spring-boot-data/.mvn/wrapper/maven-wrapper.jar create mode 100644 spring-boot-data/.mvn/wrapper/maven-wrapper.properties create mode 100644 spring-boot-data/README.md create mode 100755 spring-boot-data/mvnw create mode 100644 spring-boot-data/mvnw.cmd create mode 100644 spring-boot-data/pom.xml create mode 100644 spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java create mode 100644 spring-boot-data/src/main/resources/application.properties create mode 100644 spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java create mode 100644 spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java create mode 100644 spring-boot-data/src/test/resources/application.properties diff --git a/spring-boot-data/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot-data/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000..042d184cb5 --- /dev/null +++ b/spring-boot-data/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,114 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.util.Properties; + +public class MavenWrapperDownloader { + + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = + "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: : " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/spring-boot-data/.mvn/wrapper/maven-wrapper.jar b/spring-boot-data/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..01e67997377a393fd672c7dcde9dccbedf0cb1e9 GIT binary patch literal 48337 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + wget "$jarUrl" -O "$wrapperJarPath" + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + curl -o "$wrapperJarPath" "$jarUrl" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-boot-data/mvnw.cmd b/spring-boot-data/mvnw.cmd new file mode 100644 index 0000000000..e5cfb0ae9e --- /dev/null +++ b/spring-boot-data/mvnw.cmd @@ -0,0 +1,161 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" +FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + echo Found %WRAPPER_JAR% +) else ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" + echo Finished downloading %WRAPPER_JAR% +) +@REM End of extension + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/spring-boot-data/pom.xml b/spring-boot-data/pom.xml new file mode 100644 index 0000000000..9ef4cc69c8 --- /dev/null +++ b/spring-boot-data/pom.xml @@ -0,0 +1,122 @@ + + + 4.0.0 + spring-boot-data + war + spring-boot-data + Spring Boot Data Module + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + spring-boot + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-war-plugin + + + + pl.project13.maven + git-commit-id-plugin + ${git-commit-id-plugin.version} + + + get-the-git-infos + + revision + + initialize + + + validate-the-git-infos + + validateRevision + + package + + + + true + ${project.build.outputDirectory}/git.properties + + + + + + + + + autoconfiguration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + **/*IntegrationTest.java + **/*IntTest.java + + + **/AutoconfigurationTest.java + + + + + + + json + + + + + + + + + + com.baeldung.SpringBootDataApplication + 2.2.4 + + + \ No newline at end of file diff --git a/spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java b/spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java new file mode 100644 index 0000000000..3aa093bb41 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootDataApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootDataApplication.class, args); + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java new file mode 100644 index 0000000000..f131d17196 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java @@ -0,0 +1,70 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class Contact { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private LocalDate birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public LocalDateTime getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(LocalDateTime lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public Contact() { + } + + public Contact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java new file mode 100644 index 0000000000..79037e1038 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java @@ -0,0 +1,13 @@ +package com.baeldung.jsondateformat; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ContactApp { + + public static void main(String[] args) { + SpringApplication.run(ContactApp.class, args); + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java new file mode 100644 index 0000000000..7a20ebfa51 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java @@ -0,0 +1,33 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.time.format.DateTimeFormatter; + +@Configuration +public class ContactAppConfig { + + private static final String dateFormat = "yyyy-MM-dd"; + + private static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; + + @Bean + @ConditionalOnProperty(value = "spring.jackson.date-format", matchIfMissing = true, havingValue = "none") + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + return new Jackson2ObjectMapperBuilderCustomizer() { + @Override + public void customize(Jackson2ObjectMapperBuilder builder) { + builder.simpleDateFormat(dateTimeFormat); + builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat))); + builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat))); + } + }; + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java new file mode 100644 index 0000000000..8894d82fc7 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java @@ -0,0 +1,77 @@ +package com.baeldung.jsondateformat; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@RestController +@RequestMapping(value = "/contacts") +public class ContactController { + + @GetMapping + public List getContacts() { + List contacts = new ArrayList<>(); + + Contact contact1 = new Contact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + Contact contact2 = new Contact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + Contact contact3 = new Contact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/javaUtilDate") + public List getContactsWithJavaUtilDate() { + List contacts = new ArrayList<>(); + + ContactWithJavaUtilDate contact1 = new ContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); + ContactWithJavaUtilDate contact2 = new ContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); + ContactWithJavaUtilDate contact3 = new ContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/plain") + public List getPlainContacts() { + List contacts = new ArrayList<>(); + + PlainContact contact1 = new PlainContact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + PlainContact contact2 = new PlainContact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + PlainContact contact3 = new PlainContact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/plainWithJavaUtilDate") + public List getPlainContactsWithJavaUtilDate() { + List contacts = new ArrayList<>(); + + PlainContactWithJavaUtilDate contact1 = new PlainContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); + PlainContactWithJavaUtilDate contact2 = new PlainContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); + PlainContactWithJavaUtilDate contact3 = new PlainContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java new file mode 100644 index 0000000000..5a1c508098 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java @@ -0,0 +1,69 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class ContactWithJavaUtilDate { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Date getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(Date lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public ContactWithJavaUtilDate() { + } + + public ContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java new file mode 100644 index 0000000000..7e9e53d205 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java @@ -0,0 +1,66 @@ +package com.baeldung.jsondateformat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class PlainContact { + + private String name; + private String address; + private String phone; + + private LocalDate birthday; + + private LocalDateTime lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public LocalDateTime getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(LocalDateTime lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public PlainContact() { + } + + public PlainContact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java new file mode 100644 index 0000000000..daefb15543 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java @@ -0,0 +1,69 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class PlainContactWithJavaUtilDate { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Date getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(Date lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public PlainContactWithJavaUtilDate() { + } + + public PlainContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/resources/application.properties b/spring-boot-data/src/main/resources/application.properties new file mode 100644 index 0000000000..845b783634 --- /dev/null +++ b/spring-boot-data/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.jackson.date-format=yyyy-MM-dd HH:mm:ss +spring.jackson.time-zone=Europe/Zagreb \ No newline at end of file diff --git a/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java new file mode 100644 index 0000000000..f76440d1bc --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java @@ -0,0 +1,100 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.text.ParseException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT, classes = ContactApp.class) +@TestPropertySource(properties = { + "spring.jackson.date-format=yyyy-MM-dd HH:mm:ss" +}) +public class ContactAppIntegrationTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate; + + @Test + public void givenJsonFormatAnnotationAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException, ParseException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenJsonFormatAnnotationAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/javaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plainWithJavaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test(expected = DateTimeParseException.class) + public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenNotApplyFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plain", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } + +} diff --git a/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java new file mode 100644 index 0000000000..c286012653 --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java @@ -0,0 +1,67 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT, classes = ContactApp.class) +public class ContactAppWithObjectMapperCustomizerIntegrationTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + @Autowired + private TestRestTemplate restTemplate; + + @LocalServerPort + private int port; + + @Test + public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plainWithJavaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plain", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + +} diff --git a/spring-boot-data/src/test/resources/application.properties b/spring-boot-data/src/test/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 From ba969047a21b2bd5bb41ae605cb92d77bd8b7a46 Mon Sep 17 00:00:00 2001 From: mprevisic Date: Tue, 19 Feb 2019 14:19:41 +0100 Subject: [PATCH 065/496] [BAEL-2533] clean up - removed code examples from old module --- .../com/baeldung/jsondateformat/Contact.java | 70 -------------- .../baeldung/jsondateformat/ContactApp.java | 13 --- .../jsondateformat/ContactAppConfig.java | 33 ------- .../jsondateformat/ContactController.java | 77 --------------- .../ContactWithJavaUtilDate.java | 69 ------------- .../baeldung/jsondateformat/PlainContact.java | 66 ------------- .../PlainContactWithJavaUtilDate.java | 69 ------------- .../src/main/resources/application.properties | 5 +- .../ContactAppIntegrationTest.java | 96 ------------------- ...ObjectMapperCustomizerIntegrationTest.java | 63 ------------ 10 files changed, 1 insertion(+), 560 deletions(-) delete mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/Contact.java delete mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/ContactApp.java delete mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java delete mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/ContactController.java delete mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java delete mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContact.java delete mode 100644 spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java delete mode 100644 spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java delete mode 100644 spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/Contact.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/Contact.java deleted file mode 100644 index f131d17196..0000000000 --- a/spring-boot/src/main/java/com/baeldung/jsondateformat/Contact.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.baeldung.jsondateformat; - -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -public class Contact { - - private String name; - private String address; - private String phone; - - @JsonFormat(pattern="yyyy-MM-dd") - private LocalDate birthday; - - @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") - private LocalDateTime lastUpdate; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - - public LocalDate getBirthday() { - return birthday; - } - - public void setBirthday(LocalDate birthday) { - this.birthday = birthday; - } - - public LocalDateTime getLastUpdate() { - return lastUpdate; - } - - public void setLastUpdate(LocalDateTime lastUpdate) { - this.lastUpdate = lastUpdate; - } - - public Contact() { - } - - public Contact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { - this.name = name; - this.address = address; - this.phone = phone; - this.birthday = birthday; - this.lastUpdate = lastUpdate; - } -} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactApp.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactApp.java deleted file mode 100644 index 79037e1038..0000000000 --- a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactApp.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.jsondateformat; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class ContactApp { - - public static void main(String[] args) { - SpringApplication.run(ContactApp.class, args); - } - -} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java deleted file mode 100644 index 7a20ebfa51..0000000000 --- a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.baeldung.jsondateformat; - -import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; -import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; - -import java.time.format.DateTimeFormatter; - -@Configuration -public class ContactAppConfig { - - private static final String dateFormat = "yyyy-MM-dd"; - - private static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; - - @Bean - @ConditionalOnProperty(value = "spring.jackson.date-format", matchIfMissing = true, havingValue = "none") - public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { - return new Jackson2ObjectMapperBuilderCustomizer() { - @Override - public void customize(Jackson2ObjectMapperBuilder builder) { - builder.simpleDateFormat(dateTimeFormat); - builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat))); - builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat))); - } - }; - } - -} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactController.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactController.java deleted file mode 100644 index 8894d82fc7..0000000000 --- a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactController.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.baeldung.jsondateformat; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -@RestController -@RequestMapping(value = "/contacts") -public class ContactController { - - @GetMapping - public List getContacts() { - List contacts = new ArrayList<>(); - - Contact contact1 = new Contact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); - Contact contact2 = new Contact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); - Contact contact3 = new Contact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); - - contacts.add(contact1); - contacts.add(contact2); - contacts.add(contact3); - - return contacts; - } - - @GetMapping("/javaUtilDate") - public List getContactsWithJavaUtilDate() { - List contacts = new ArrayList<>(); - - ContactWithJavaUtilDate contact1 = new ContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); - ContactWithJavaUtilDate contact2 = new ContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); - ContactWithJavaUtilDate contact3 = new ContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); - - contacts.add(contact1); - contacts.add(contact2); - contacts.add(contact3); - - return contacts; - } - - @GetMapping("/plain") - public List getPlainContacts() { - List contacts = new ArrayList<>(); - - PlainContact contact1 = new PlainContact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); - PlainContact contact2 = new PlainContact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); - PlainContact contact3 = new PlainContact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); - - contacts.add(contact1); - contacts.add(contact2); - contacts.add(contact3); - - return contacts; - } - - @GetMapping("/plainWithJavaUtilDate") - public List getPlainContactsWithJavaUtilDate() { - List contacts = new ArrayList<>(); - - PlainContactWithJavaUtilDate contact1 = new PlainContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); - PlainContactWithJavaUtilDate contact2 = new PlainContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); - PlainContactWithJavaUtilDate contact3 = new PlainContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); - - contacts.add(contact1); - contacts.add(contact2); - contacts.add(contact3); - - return contacts; - } - -} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java deleted file mode 100644 index 5a1c508098..0000000000 --- a/spring-boot/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.baeldung.jsondateformat; - -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.util.Date; - -public class ContactWithJavaUtilDate { - - private String name; - private String address; - private String phone; - - @JsonFormat(pattern="yyyy-MM-dd") - private Date birthday; - - @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") - private Date lastUpdate; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - - public Date getBirthday() { - return birthday; - } - - public void setBirthday(Date birthday) { - this.birthday = birthday; - } - - public Date getLastUpdate() { - return lastUpdate; - } - - public void setLastUpdate(Date lastUpdate) { - this.lastUpdate = lastUpdate; - } - - public ContactWithJavaUtilDate() { - } - - public ContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { - this.name = name; - this.address = address; - this.phone = phone; - this.birthday = birthday; - this.lastUpdate = lastUpdate; - } -} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContact.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContact.java deleted file mode 100644 index 7e9e53d205..0000000000 --- a/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContact.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.baeldung.jsondateformat; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -public class PlainContact { - - private String name; - private String address; - private String phone; - - private LocalDate birthday; - - private LocalDateTime lastUpdate; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - - public LocalDate getBirthday() { - return birthday; - } - - public void setBirthday(LocalDate birthday) { - this.birthday = birthday; - } - - public LocalDateTime getLastUpdate() { - return lastUpdate; - } - - public void setLastUpdate(LocalDateTime lastUpdate) { - this.lastUpdate = lastUpdate; - } - - public PlainContact() { - } - - public PlainContact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { - this.name = name; - this.address = address; - this.phone = phone; - this.birthday = birthday; - this.lastUpdate = lastUpdate; - } -} diff --git a/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java b/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java deleted file mode 100644 index daefb15543..0000000000 --- a/spring-boot/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.baeldung.jsondateformat; - -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.util.Date; - -public class PlainContactWithJavaUtilDate { - - private String name; - private String address; - private String phone; - - @JsonFormat(pattern="yyyy-MM-dd") - private Date birthday; - - @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") - private Date lastUpdate; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - - public Date getBirthday() { - return birthday; - } - - public void setBirthday(Date birthday) { - this.birthday = birthday; - } - - public Date getLastUpdate() { - return lastUpdate; - } - - public void setLastUpdate(Date lastUpdate) { - this.lastUpdate = lastUpdate; - } - - public PlainContactWithJavaUtilDate() { - } - - public PlainContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { - this.name = name; - this.address = address; - this.phone = phone; - this.birthday = birthday; - this.lastUpdate = lastUpdate; - } -} diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 00c251d823..6d24c7887f 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -71,7 +71,4 @@ chaos.monkey.watcher.service=true #Repository watcher active chaos.monkey.watcher.repository=false #Component watcher active -chaos.monkey.watcher.component=false - -spring.jackson.date-format=yyyy-MM-dd HH:mm:ss -spring.jackson.time-zone=Europe/Zagreb +chaos.monkey.watcher.component=false \ No newline at end of file diff --git a/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java deleted file mode 100644 index 86af985d8a..0000000000 --- a/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.baeldung.jsondateformat; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import java.io.IOException; -import java.text.ParseException; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = DEFINED_PORT, classes = ContactApp.class) -@TestPropertySource(properties = { - "spring.jackson.date-format=yyyy-MM-dd HH:mm:ss" -}) -public class ContactAppIntegrationTest { - - private final ObjectMapper mapper = new ObjectMapper(); - - @Autowired - TestRestTemplate restTemplate; - - @Test - public void givenJsonFormatAnnotationAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException, ParseException { - ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts", String.class); - - assertEquals(200, response.getStatusCodeValue()); - - List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); - - LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); - LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - - assertNotNull(birthdayDate); - assertNotNull(lastUpdateTime); - } - - @Test - public void givenJsonFormatAnnotationAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { - ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/javaUtilDate", String.class); - - assertEquals(200, response.getStatusCodeValue()); - - List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); - - LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); - LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - - assertNotNull(birthdayDate); - assertNotNull(lastUpdateTime); - } - - @Test - public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { - ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/plainWithJavaUtilDate", String.class); - - assertEquals(200, response.getStatusCodeValue()); - - List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); - - LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); - LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - - assertNotNull(birthdayDate); - assertNotNull(lastUpdateTime); - } - - @Test(expected = DateTimeParseException.class) - public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenNotApplyFormat() throws IOException { - ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/plain", String.class); - - assertEquals(200, response.getStatusCodeValue()); - - List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); - - LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); - LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - } - -} diff --git a/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java deleted file mode 100644 index 554283d758..0000000000 --- a/spring-boot/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.baeldung.jsondateformat; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.junit4.SpringRunner; - -import java.io.IOException; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = DEFINED_PORT, classes = ContactApp.class) -public class ContactAppWithObjectMapperCustomizerIntegrationTest { - - private final ObjectMapper mapper = new ObjectMapper(); - - @Autowired - TestRestTemplate restTemplate; - - @Test - public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { - ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/plainWithJavaUtilDate", String.class); - - assertEquals(200, response.getStatusCodeValue()); - - List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); - - LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); - LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - - assertNotNull(birthdayDate); - assertNotNull(lastUpdateTime); - } - - @Test - public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException { - ResponseEntity response = restTemplate.getForEntity("http://localhost:8080/contacts/plain", String.class); - - assertEquals(200, response.getStatusCodeValue()); - - List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); - - LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); - LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - - assertNotNull(birthdayDate); - assertNotNull(lastUpdateTime); - } - -} From 578d35d25d19ce5f7d106e0085a2b7b127e73e5f Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Tue, 19 Feb 2019 16:23:44 -0300 Subject: [PATCH 066/496] Move and Update Rest and Http Message Converter Article: moved code (mostly commented out) changed readme file added spring boot exampel simply adding bean, for xml too --- spring-boot-rest/README.md | 1 + spring-boot-rest/pom.xml | 19 +++++++-- .../com/baeldung/persistence/model/Foo.java | 3 ++ .../java/com/baeldung/spring/WebConfig.java | 41 ++++++++++++++++++- .../main/resources/WEB-INF/api-servlet.xml | 41 +++++++++++++++++++ spring-rest/README.md | 1 - spring-rest/pom.xml | 11 ----- .../baeldung/sampleapp/config/WebConfig.java | 14 +------ .../com/baeldung/sampleapp/web/dto/Foo.java | 3 -- .../src/main/webapp/WEB-INF/api-servlet.xml | 10 ----- 10 files changed, 101 insertions(+), 43 deletions(-) create mode 100644 spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 3fbd21f24e..f7f7ec6598 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -6,3 +6,4 @@ Module for the articles that are part of the Spring REST E-book: 4. [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration) 5. [HATEOAS for a Spring REST Service](http://www.baeldung.com/rest-api-discoverability-with-spring) 6. [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability) +7. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml index 3c8c4d7486..decaccd148 100644 --- a/spring-boot-rest/pom.xml +++ b/spring-boot-rest/pom.xml @@ -25,16 +25,26 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml - + + + org.springframework + spring-oxm + + + com.thoughtworks.xstream + xstream + ${xstream.version} + + com.h2database h2 - + org.springframework.boot spring-boot-starter-data-jpa - - + + @@ -67,5 +77,6 @@ com.baeldung.SpringBootRestApplication 27.0.1-jre + 1.4.11.1 diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java index 9af3d07bed..f19d1c0e0b 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java @@ -8,6 +8,9 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("Foo") @Entity public class Foo implements Serializable { diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index 80ee975e84..f581e4ec10 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -1,10 +1,49 @@ package com.baeldung.spring; +import java.util.List; + +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportResource; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; +import org.springframework.oxm.xstream.XStreamMarshaller; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - @Configuration +// If we want to enable xml configurations for message-converter: +// @ImportResource("classpath:WEB-INF/api-servlet.xml") public class WebConfig implements WebMvcConfigurer { + // @Override + // public void configureMessageConverters(final List> messageConverters) { + // messageConverters.add(new MappingJackson2HttpMessageConverter()); + // messageConverters.add(createXmlHttpMessageConverter()); + // } + // + // private HttpMessageConverter createXmlHttpMessageConverter() { + // final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); + // + // final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); + // xstreamMarshaller.setAutodetectAnnotations(true); + // xmlConverter.setMarshaller(xstreamMarshaller); + // xmlConverter.setUnmarshaller(xstreamMarshaller); + // + // return xmlConverter; + // } + + // Another possibility is to create a bean which will be automatically added to the Spring Boot Autoconfigurations +// @Bean +// public HttpMessageConverter createXmlHttpMessageConverter() { +// final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); +// +// final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); +// xstreamMarshaller.setAutodetectAnnotations(true); +// xmlConverter.setMarshaller(xstreamMarshaller); +// xmlConverter.setUnmarshaller(xstreamMarshaller); +// +// return xmlConverter; +// } + } \ No newline at end of file diff --git a/spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml b/spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml new file mode 100644 index 0000000000..78e38e1448 --- /dev/null +++ b/spring-boot-rest/src/main/resources/WEB-INF/api-servlet.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-rest/README.md b/spring-rest/README.md index 4921ab012c..9a2c1fd96c 100644 --- a/spring-rest/README.md +++ b/spring-rest/README.md @@ -5,7 +5,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Spring @RequestMapping](http://www.baeldung.com/spring-requestmapping) -- [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) - [Returning Custom Status Codes from Spring Controllers](http://www.baeldung.com/spring-mvc-controller-custom-http-status-code) - [A Guide to OkHttp](http://www.baeldung.com/guide-to-okhttp) - [Binary Data Formats in a Spring REST API](http://www.baeldung.com/spring-rest-api-with-binary-data-formats) diff --git a/spring-rest/pom.xml b/spring-rest/pom.xml index 5c88697cef..36934af101 100644 --- a/spring-rest/pom.xml +++ b/spring-rest/pom.xml @@ -52,10 +52,6 @@ org.springframework spring-webmvc - - org.springframework - spring-oxm - commons-fileupload commons-fileupload @@ -86,12 +82,6 @@ jackson-dataformat-xml - - com.thoughtworks.xstream - xstream - ${xstream.version} - - com.google.guava @@ -281,7 +271,6 @@ 1.4 3.1.0 3.5 - 1.4.9 20.0 diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java b/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java index d5209a520b..dc4fb9c695 100644 --- a/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java +++ b/spring-rest/src/main/java/com/baeldung/sampleapp/config/WebConfig.java @@ -8,8 +8,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; -import org.springframework.oxm.xstream.XStreamMarshaller; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -33,22 +31,12 @@ public class WebConfig implements WebMvcConfigurer { .dateFormat(new SimpleDateFormat("dd-MM-yyyy hh:mm")); messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build())); // messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); - - // messageConverters.add(createXmlHttpMessageConverter()); + // messageConverters.add(new MappingJackson2HttpMessageConverter()); // messageConverters.add(new ProtobufHttpMessageConverter()); } - private HttpMessageConverter createXmlHttpMessageConverter() { - final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); - - final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - xmlConverter.setMarshaller(xstreamMarshaller); - xmlConverter.setUnmarshaller(xstreamMarshaller); - - return xmlConverter; - } */ } diff --git a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java b/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java index 186df8e678..de1d76ed92 100644 --- a/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java +++ b/spring-rest/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java @@ -1,8 +1,5 @@ package com.baeldung.sampleapp.web.dto; -import com.thoughtworks.xstream.annotations.XStreamAlias; - -@XStreamAlias("Foo") public class Foo { private long id; private String name; diff --git a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml index ddb9c91792..3d83ebf6c9 100644 --- a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml +++ b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml @@ -10,21 +10,11 @@ - - - From 062b959d5a4d127a168d56045d589f0e45d8d5da Mon Sep 17 00:00:00 2001 From: vsurapaneni Date: Tue, 19 Feb 2019 15:33:40 -0500 Subject: [PATCH 067/496] BAEL-2575 --- spring-boot-datasource-issue/pom.xml | 21 +++++++++ .../pom.xml | 36 +++++++++++++++ .../DataSourceIssueSolutionApplication.java | 15 +++++++ .../pom.xml | 36 +++++++++++++++ .../DataSourceIssueSolutionApplication.java | 13 ++++++ .../src/main/resources/application.properties | 2 + .../pom.xml | 45 +++++++++++++++++++ .../DataSourceIssueSolutionApplication.java | 13 ++++++ .../src/main/resources/application.yml | 4 ++ .../spring-boot-datasource-program/pom.xml | 36 +++++++++++++++ .../DataSourceIssueSolutionApplication.java | 13 ++++++ .../datasourcedemo/DatasourceConfig.java | 18 ++++++++ .../spring-boot-datasource-properties/pom.xml | 36 +++++++++++++++ .../DataSourceIssueSolutionApplication.java | 13 ++++++ .../src/main/resources/application.properties | 4 ++ .../spring-boot-datasource-yml/pom.xml | 45 +++++++++++++++++++ .../DataSourceIssueSolutionApplication.java | 13 ++++++ .../src/main/resources/application.yml | 6 +++ 18 files changed, 369 insertions(+) create mode 100644 spring-boot-datasource-issue/pom.xml create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-program/pom.xml create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/pom.xml create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/resources/application.properties create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/pom.xml create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/resources/application.yml create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-program/pom.xml create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DatasourceConfig.java create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-properties/pom.xml create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/resources/application.properties create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-yml/pom.xml create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java create mode 100644 spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/resources/application.yml diff --git a/spring-boot-datasource-issue/pom.xml b/spring-boot-datasource-issue/pom.xml new file mode 100644 index 0000000000..2316d86e70 --- /dev/null +++ b/spring-boot-datasource-issue/pom.xml @@ -0,0 +1,21 @@ + + 4.0.0 + spring-boot-datasource-issue + pom + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + spring-boot-datasource-properties + spring-boot-datasource-exclude-program + spring-boot-datasource-exclude-properties + spring-boot-datasource-exclude-yml + spring-boot-datasource-program + spring-boot-datasource-yml + + \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/pom.xml new file mode 100644 index 0000000000..8025cc8959 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + com.baeldung + spring-boot-datasource-issue + 0.0.1-SNAPSHOT + + spring-boot-datasource-exclude-program + spring-boot-datasource-exclude-program + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + runtime + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java new file mode 100644 index 0000000000..b6c81471c4 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.datasourcedemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) +public class DataSourceIssueSolutionApplication { + + public static void main(String[] args) { + SpringApplication.run(DataSourceIssueSolutionApplication.class, args); + } + +} + diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/pom.xml new file mode 100644 index 0000000000..78d253c4f7 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + com.baeldung + spring-boot-datasource-issue + 0.0.1-SNAPSHOT + + spring-boot-datasource-exclude-properties + spring-boot-datasource-exclude-properties + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + runtime + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java new file mode 100644 index 0000000000..377a245b38 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.datasourcedemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DataSourceIssueSolutionApplication { + + public static void main(String[] args) { + SpringApplication.run(DataSourceIssueSolutionApplication.class, args); + } + +} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/resources/application.properties b/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/resources/application.properties new file mode 100644 index 0000000000..ae2b359cd0 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration + diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/pom.xml new file mode 100644 index 0000000000..1d60ea3dbf --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + + com.baeldung + spring-boot-datasource-issue + 0.0.1-SNAPSHOT + + spring-boot-datasource-exclude-yml + spring-boot-datasource-exclude-yml + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + runtime + + + org.yaml + snakeyaml + + + + + Sonatype-public + SnakeYAML repository + http://oss.sonatype.org/content/groups/public/ + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java new file mode 100644 index 0000000000..377a245b38 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.datasourcedemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DataSourceIssueSolutionApplication { + + public static void main(String[] args) { + SpringApplication.run(DataSourceIssueSolutionApplication.class, args); + } + +} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/resources/application.yml b/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/resources/application.yml new file mode 100644 index 0000000000..c574bf01a7 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/resources/application.yml @@ -0,0 +1,4 @@ +spring: + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration diff --git a/spring-boot-datasource-issue/spring-boot-datasource-program/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-program/pom.xml new file mode 100644 index 0000000000..279fcc063b --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-program/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + com.baeldung + spring-boot-datasource-issue + 0.0.1-SNAPSHOT + + spring-boot-datasource-program + spring-boot-datasource-program + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + runtime + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java new file mode 100644 index 0000000000..377a245b38 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.datasourcedemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DataSourceIssueSolutionApplication { + + public static void main(String[] args) { + SpringApplication.run(DataSourceIssueSolutionApplication.class, args); + } + +} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DatasourceConfig.java b/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DatasourceConfig.java new file mode 100644 index 0000000000..0eca032d42 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DatasourceConfig.java @@ -0,0 +1,18 @@ +package com.baeldung.datasourcedemo; + + +import javax.sql.DataSource; + +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class DatasourceConfig { + @Bean + public DataSource datasource() { + return DataSourceBuilder.create().driverClassName("com.mysql.cj.jdbc.Driver"). + url("jdbc:mysql://localhost:3306/lonar").username("root").password("Chinna@1988").build(); + } + +} \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-properties/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-properties/pom.xml new file mode 100644 index 0000000000..8a7ca75bdd --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-properties/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + + com.baeldung + spring-boot-datasource-issue + 0.0.1-SNAPSHOT + + spring-boot-datasource-properties + spring-boot-datasource-properties + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + runtime + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java new file mode 100644 index 0000000000..377a245b38 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.datasourcedemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DataSourceIssueSolutionApplication { + + public static void main(String[] args) { + SpringApplication.run(DataSourceIssueSolutionApplication.class, args); + } + +} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/resources/application.properties b/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/resources/application.properties new file mode 100644 index 0000000000..90605e9258 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/resources/application.properties @@ -0,0 +1,4 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/lonar +spring.datasource.username=root +spring.datasource.password=Chinna@1988 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver diff --git a/spring-boot-datasource-issue/spring-boot-datasource-yml/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-yml/pom.xml new file mode 100644 index 0000000000..6f474f76db --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-yml/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + + com.baeldung + spring-boot-datasource-issue + 0.0.1-SNAPSHOT + + spring-boot-datasource-yml + spring-boot-datasource-yml + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + runtime + + + org.yaml + snakeyaml + + + + + Sonatype-public + SnakeYAML repository + http://oss.sonatype.org/content/groups/public/ + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java new file mode 100644 index 0000000000..377a245b38 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.datasourcedemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DataSourceIssueSolutionApplication { + + public static void main(String[] args) { + SpringApplication.run(DataSourceIssueSolutionApplication.class, args); + } + +} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/resources/application.yml b/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/resources/application.yml new file mode 100644 index 0000000000..98d7c843e8 --- /dev/null +++ b/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/resources/application.yml @@ -0,0 +1,6 @@ +spring: + datasource: + driverClassName: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/lonar + username: root + password: Chinna@1988 From 9d395d7154cafb0ddcc868a85554115e75dd41bb Mon Sep 17 00:00:00 2001 From: mprevisic Date: Tue, 19 Feb 2019 21:49:11 +0100 Subject: [PATCH 068/496] [BAEL-2533] removed maven wrapper --- .../.mvn/wrapper/MavenWrapperDownloader.java | 114 ------- .../.mvn/wrapper/maven-wrapper.jar | Bin 48337 -> 0 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 - spring-boot-data/mvnw | 286 ------------------ spring-boot-data/mvnw.cmd | 161 ---------- 5 files changed, 562 deletions(-) delete mode 100644 spring-boot-data/.mvn/wrapper/MavenWrapperDownloader.java delete mode 100644 spring-boot-data/.mvn/wrapper/maven-wrapper.jar delete mode 100644 spring-boot-data/.mvn/wrapper/maven-wrapper.properties delete mode 100755 spring-boot-data/mvnw delete mode 100644 spring-boot-data/mvnw.cmd diff --git a/spring-boot-data/.mvn/wrapper/MavenWrapperDownloader.java b/spring-boot-data/.mvn/wrapper/MavenWrapperDownloader.java deleted file mode 100644 index 042d184cb5..0000000000 --- a/spring-boot-data/.mvn/wrapper/MavenWrapperDownloader.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. -*/ - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Properties; - -public class MavenWrapperDownloader { - - /** - * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. - */ - private static final String DEFAULT_DOWNLOAD_URL = - "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; - - /** - * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to - * use instead of the default one. - */ - private static final String MAVEN_WRAPPER_PROPERTIES_PATH = - ".mvn/wrapper/maven-wrapper.properties"; - - /** - * Path where the maven-wrapper.jar will be saved to. - */ - private static final String MAVEN_WRAPPER_JAR_PATH = - ".mvn/wrapper/maven-wrapper.jar"; - - /** - * Name of the property which should be used to override the default download url for the wrapper. - */ - private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; - - public static void main(String args[]) { - System.out.println("- Downloader started"); - File baseDirectory = new File(args[0]); - System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); - - // If the maven-wrapper.properties exists, read it and check if it contains a custom - // wrapperUrl parameter. - File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); - String url = DEFAULT_DOWNLOAD_URL; - if (mavenWrapperPropertyFile.exists()) { - FileInputStream mavenWrapperPropertyFileInputStream = null; - try { - mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); - Properties mavenWrapperProperties = new Properties(); - mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); - url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); - } catch (IOException e) { - System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); - } finally { - try { - if (mavenWrapperPropertyFileInputStream != null) { - mavenWrapperPropertyFileInputStream.close(); - } - } catch (IOException e) { - // Ignore ... - } - } - } - System.out.println("- Downloading from: : " + url); - - File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); - if (!outputFile.getParentFile().exists()) { - if (!outputFile.getParentFile().mkdirs()) { - System.out.println( - "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); - } - } - System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); - try { - downloadFileFromURL(url, outputFile); - System.out.println("Done"); - System.exit(0); - } catch (Throwable e) { - System.out.println("- Error downloading"); - e.printStackTrace(); - System.exit(1); - } - } - - private static void downloadFileFromURL(String urlString, File destination) throws Exception { - URL website = new URL(urlString); - ReadableByteChannel rbc; - rbc = Channels.newChannel(website.openStream()); - FileOutputStream fos = new FileOutputStream(destination); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - fos.close(); - rbc.close(); - } - -} diff --git a/spring-boot-data/.mvn/wrapper/maven-wrapper.jar b/spring-boot-data/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 01e67997377a393fd672c7dcde9dccbedf0cb1e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48337 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/spring-boot-data/mvnw.cmd b/spring-boot-data/mvnw.cmd deleted file mode 100644 index e5cfb0ae9e..0000000000 --- a/spring-boot-data/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% From c5d9aceb86b450b2a022c39acc73ddc128b5fb11 Mon Sep 17 00:00:00 2001 From: vsurapaneni Date: Tue, 19 Feb 2019 16:09:52 -0500 Subject: [PATCH 069/496] fixed the mix up with another pr. --- spring-boot-datasource-issue/pom.xml | 21 --------- .../pom.xml | 36 --------------- .../DataSourceIssueSolutionApplication.java | 15 ------- .../pom.xml | 36 --------------- .../DataSourceIssueSolutionApplication.java | 13 ------ .../src/main/resources/application.properties | 2 - .../pom.xml | 45 ------------------- .../DataSourceIssueSolutionApplication.java | 13 ------ .../src/main/resources/application.yml | 4 -- .../spring-boot-datasource-program/pom.xml | 36 --------------- .../DataSourceIssueSolutionApplication.java | 13 ------ .../datasourcedemo/DatasourceConfig.java | 18 -------- .../spring-boot-datasource-properties/pom.xml | 36 --------------- .../DataSourceIssueSolutionApplication.java | 13 ------ .../src/main/resources/application.properties | 4 -- .../spring-boot-datasource-yml/pom.xml | 45 ------------------- .../DataSourceIssueSolutionApplication.java | 13 ------ .../src/main/resources/application.yml | 6 --- 18 files changed, 369 deletions(-) delete mode 100644 spring-boot-datasource-issue/pom.xml delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-program/pom.xml delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/pom.xml delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/resources/application.properties delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/pom.xml delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/resources/application.yml delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-program/pom.xml delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DatasourceConfig.java delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-properties/pom.xml delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/resources/application.properties delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-yml/pom.xml delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java delete mode 100644 spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/resources/application.yml diff --git a/spring-boot-datasource-issue/pom.xml b/spring-boot-datasource-issue/pom.xml deleted file mode 100644 index 2316d86e70..0000000000 --- a/spring-boot-datasource-issue/pom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - 4.0.0 - spring-boot-datasource-issue - pom - - - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../parent-boot-2 - - - - spring-boot-datasource-properties - spring-boot-datasource-exclude-program - spring-boot-datasource-exclude-properties - spring-boot-datasource-exclude-yml - spring-boot-datasource-program - spring-boot-datasource-yml - - \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/pom.xml deleted file mode 100644 index 8025cc8959..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - 4.0.0 - - com.baeldung - spring-boot-datasource-issue - 0.0.1-SNAPSHOT - - spring-boot-datasource-exclude-program - spring-boot-datasource-exclude-program - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - mysql - mysql-connector-java - runtime - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java deleted file mode 100644 index b6c81471c4..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-exclude-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.datasourcedemo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; - -@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) -public class DataSourceIssueSolutionApplication { - - public static void main(String[] args) { - SpringApplication.run(DataSourceIssueSolutionApplication.class, args); - } - -} - diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/pom.xml deleted file mode 100644 index 78d253c4f7..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - 4.0.0 - - com.baeldung - spring-boot-datasource-issue - 0.0.1-SNAPSHOT - - spring-boot-datasource-exclude-properties - spring-boot-datasource-exclude-properties - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - mysql - mysql-connector-java - runtime - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java deleted file mode 100644 index 377a245b38..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.datasourcedemo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class DataSourceIssueSolutionApplication { - - public static void main(String[] args) { - SpringApplication.run(DataSourceIssueSolutionApplication.class, args); - } - -} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/resources/application.properties b/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/resources/application.properties deleted file mode 100644 index ae2b359cd0..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-exclude-properties/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/pom.xml deleted file mode 100644 index 1d60ea3dbf..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - 4.0.0 - - com.baeldung - spring-boot-datasource-issue - 0.0.1-SNAPSHOT - - spring-boot-datasource-exclude-yml - spring-boot-datasource-exclude-yml - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - mysql - mysql-connector-java - runtime - - - org.yaml - snakeyaml - - - - - Sonatype-public - SnakeYAML repository - http://oss.sonatype.org/content/groups/public/ - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java deleted file mode 100644 index 377a245b38..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.datasourcedemo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class DataSourceIssueSolutionApplication { - - public static void main(String[] args) { - SpringApplication.run(DataSourceIssueSolutionApplication.class, args); - } - -} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/resources/application.yml b/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/resources/application.yml deleted file mode 100644 index c574bf01a7..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-exclude-yml/src/main/resources/application.yml +++ /dev/null @@ -1,4 +0,0 @@ -spring: - autoconfigure: - exclude: - - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration diff --git a/spring-boot-datasource-issue/spring-boot-datasource-program/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-program/pom.xml deleted file mode 100644 index 279fcc063b..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-program/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - 4.0.0 - - com.baeldung - spring-boot-datasource-issue - 0.0.1-SNAPSHOT - - spring-boot-datasource-program - spring-boot-datasource-program - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - mysql - mysql-connector-java - runtime - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java deleted file mode 100644 index 377a245b38..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.datasourcedemo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class DataSourceIssueSolutionApplication { - - public static void main(String[] args) { - SpringApplication.run(DataSourceIssueSolutionApplication.class, args); - } - -} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DatasourceConfig.java b/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DatasourceConfig.java deleted file mode 100644 index 0eca032d42..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-program/src/main/java/com/baeldung/datasourcedemo/DatasourceConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.datasourcedemo; - - -import javax.sql.DataSource; - -import org.springframework.boot.jdbc.DataSourceBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class DatasourceConfig { - @Bean - public DataSource datasource() { - return DataSourceBuilder.create().driverClassName("com.mysql.cj.jdbc.Driver"). - url("jdbc:mysql://localhost:3306/lonar").username("root").password("Chinna@1988").build(); - } - -} \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-properties/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-properties/pom.xml deleted file mode 100644 index 8a7ca75bdd..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-properties/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - 4.0.0 - - com.baeldung - spring-boot-datasource-issue - 0.0.1-SNAPSHOT - - spring-boot-datasource-properties - spring-boot-datasource-properties - - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - mysql - mysql-connector-java - runtime - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java deleted file mode 100644 index 377a245b38..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.datasourcedemo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class DataSourceIssueSolutionApplication { - - public static void main(String[] args) { - SpringApplication.run(DataSourceIssueSolutionApplication.class, args); - } - -} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/resources/application.properties b/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/resources/application.properties deleted file mode 100644 index 90605e9258..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-properties/src/main/resources/application.properties +++ /dev/null @@ -1,4 +0,0 @@ -spring.datasource.url=jdbc:mysql://localhost:3306/lonar -spring.datasource.username=root -spring.datasource.password=Chinna@1988 -spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver diff --git a/spring-boot-datasource-issue/spring-boot-datasource-yml/pom.xml b/spring-boot-datasource-issue/spring-boot-datasource-yml/pom.xml deleted file mode 100644 index 6f474f76db..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-yml/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - 4.0.0 - - com.baeldung - spring-boot-datasource-issue - 0.0.1-SNAPSHOT - - spring-boot-datasource-yml - spring-boot-datasource-yml - - 1.8 - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - mysql - mysql-connector-java - runtime - - - org.yaml - snakeyaml - - - - - Sonatype-public - SnakeYAML repository - http://oss.sonatype.org/content/groups/public/ - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - \ No newline at end of file diff --git a/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java b/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java deleted file mode 100644 index 377a245b38..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/java/com/baeldung/datasourcedemo/DataSourceIssueSolutionApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.datasourcedemo; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class DataSourceIssueSolutionApplication { - - public static void main(String[] args) { - SpringApplication.run(DataSourceIssueSolutionApplication.class, args); - } - -} diff --git a/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/resources/application.yml b/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/resources/application.yml deleted file mode 100644 index 98d7c843e8..0000000000 --- a/spring-boot-datasource-issue/spring-boot-datasource-yml/src/main/resources/application.yml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - datasource: - driverClassName: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/lonar - username: root - password: Chinna@1988 From c8ea52ee0162408e921b0d6bba338d6c3b511539 Mon Sep 17 00:00:00 2001 From: Marko Previsic Date: Wed, 20 Feb 2019 03:58:39 +0100 Subject: [PATCH 070/496] [BAEL-2533] Format the JSON Date output in Spring Boot (#6376) * [BAEL-2533] formatting json date output in spring boot * [BAEL-2533] removed unused import * [BAEL-2533] moved code examples to new module * [BAEL-2533] clean up - removed code examples from old module * [BAEL-2533] removed maven wrapper --- spring-boot-data/README.md | 0 spring-boot-data/pom.xml | 122 ++++++++++++++++++ .../baeldung/SpringBootDataApplication.java | 13 ++ .../com/baeldung/jsondateformat/Contact.java | 70 ++++++++++ .../baeldung/jsondateformat/ContactApp.java | 13 ++ .../jsondateformat/ContactAppConfig.java | 33 +++++ .../jsondateformat/ContactController.java | 77 +++++++++++ .../ContactWithJavaUtilDate.java | 69 ++++++++++ .../baeldung/jsondateformat/PlainContact.java | 66 ++++++++++ .../PlainContactWithJavaUtilDate.java | 69 ++++++++++ .../src/main/resources/application.properties | 2 + .../ContactAppIntegrationTest.java | 100 ++++++++++++++ ...ObjectMapperCustomizerIntegrationTest.java | 67 ++++++++++ .../src/test/resources/application.properties | 0 .../src/main/resources/application.properties | 3 - 15 files changed, 701 insertions(+), 3 deletions(-) create mode 100644 spring-boot-data/README.md create mode 100644 spring-boot-data/pom.xml create mode 100644 spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java create mode 100644 spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java create mode 100644 spring-boot-data/src/main/resources/application.properties create mode 100644 spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java create mode 100644 spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java create mode 100644 spring-boot-data/src/test/resources/application.properties diff --git a/spring-boot-data/README.md b/spring-boot-data/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-data/pom.xml b/spring-boot-data/pom.xml new file mode 100644 index 0000000000..9ef4cc69c8 --- /dev/null +++ b/spring-boot-data/pom.xml @@ -0,0 +1,122 @@ + + + 4.0.0 + spring-boot-data + war + spring-boot-data + Spring Boot Data Module + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + spring-boot + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-war-plugin + + + + pl.project13.maven + git-commit-id-plugin + ${git-commit-id-plugin.version} + + + get-the-git-infos + + revision + + initialize + + + validate-the-git-infos + + validateRevision + + package + + + + true + ${project.build.outputDirectory}/git.properties + + + + + + + + + autoconfiguration + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + **/*IntegrationTest.java + **/*IntTest.java + + + **/AutoconfigurationTest.java + + + + + + + json + + + + + + + + + + com.baeldung.SpringBootDataApplication + 2.2.4 + + + \ No newline at end of file diff --git a/spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java b/spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java new file mode 100644 index 0000000000..3aa093bb41 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/SpringBootDataApplication.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootDataApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootDataApplication.class, args); + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java new file mode 100644 index 0000000000..f131d17196 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/Contact.java @@ -0,0 +1,70 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class Contact { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private LocalDate birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public LocalDateTime getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(LocalDateTime lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public Contact() { + } + + public Contact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java new file mode 100644 index 0000000000..79037e1038 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactApp.java @@ -0,0 +1,13 @@ +package com.baeldung.jsondateformat; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ContactApp { + + public static void main(String[] args) { + SpringApplication.run(ContactApp.class, args); + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java new file mode 100644 index 0000000000..7a20ebfa51 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactAppConfig.java @@ -0,0 +1,33 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.time.format.DateTimeFormatter; + +@Configuration +public class ContactAppConfig { + + private static final String dateFormat = "yyyy-MM-dd"; + + private static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; + + @Bean + @ConditionalOnProperty(value = "spring.jackson.date-format", matchIfMissing = true, havingValue = "none") + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + return new Jackson2ObjectMapperBuilderCustomizer() { + @Override + public void customize(Jackson2ObjectMapperBuilder builder) { + builder.simpleDateFormat(dateTimeFormat); + builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(dateFormat))); + builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat))); + } + }; + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java new file mode 100644 index 0000000000..8894d82fc7 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactController.java @@ -0,0 +1,77 @@ +package com.baeldung.jsondateformat; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@RestController +@RequestMapping(value = "/contacts") +public class ContactController { + + @GetMapping + public List getContacts() { + List contacts = new ArrayList<>(); + + Contact contact1 = new Contact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + Contact contact2 = new Contact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + Contact contact3 = new Contact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/javaUtilDate") + public List getContactsWithJavaUtilDate() { + List contacts = new ArrayList<>(); + + ContactWithJavaUtilDate contact1 = new ContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); + ContactWithJavaUtilDate contact2 = new ContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); + ContactWithJavaUtilDate contact3 = new ContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/plain") + public List getPlainContacts() { + List contacts = new ArrayList<>(); + + PlainContact contact1 = new PlainContact("John Doe", "123 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + PlainContact contact2 = new PlainContact("John Doe 2", "124 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + PlainContact contact3 = new PlainContact("John Doe 3", "125 Sesame Street", "123-456-789", LocalDate.now(), LocalDateTime.now()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + + @GetMapping("/plainWithJavaUtilDate") + public List getPlainContactsWithJavaUtilDate() { + List contacts = new ArrayList<>(); + + PlainContactWithJavaUtilDate contact1 = new PlainContactWithJavaUtilDate("John Doe", "123 Sesame Street", "123-456-789", new Date(), new Date()); + PlainContactWithJavaUtilDate contact2 = new PlainContactWithJavaUtilDate("John Doe 2", "124 Sesame Street", "123-456-789", new Date(), new Date()); + PlainContactWithJavaUtilDate contact3 = new PlainContactWithJavaUtilDate("John Doe 3", "125 Sesame Street", "123-456-789", new Date(), new Date()); + + contacts.add(contact1); + contacts.add(contact2); + contacts.add(contact3); + + return contacts; + } + +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java new file mode 100644 index 0000000000..5a1c508098 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/ContactWithJavaUtilDate.java @@ -0,0 +1,69 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class ContactWithJavaUtilDate { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Date getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(Date lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public ContactWithJavaUtilDate() { + } + + public ContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java new file mode 100644 index 0000000000..7e9e53d205 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContact.java @@ -0,0 +1,66 @@ +package com.baeldung.jsondateformat; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +public class PlainContact { + + private String name; + private String address; + private String phone; + + private LocalDate birthday; + + private LocalDateTime lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public LocalDate getBirthday() { + return birthday; + } + + public void setBirthday(LocalDate birthday) { + this.birthday = birthday; + } + + public LocalDateTime getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(LocalDateTime lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public PlainContact() { + } + + public PlainContact(String name, String address, String phone, LocalDate birthday, LocalDateTime lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java new file mode 100644 index 0000000000..daefb15543 --- /dev/null +++ b/spring-boot-data/src/main/java/com/baeldung/jsondateformat/PlainContactWithJavaUtilDate.java @@ -0,0 +1,69 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.util.Date; + +public class PlainContactWithJavaUtilDate { + + private String name; + private String address; + private String phone; + + @JsonFormat(pattern="yyyy-MM-dd") + private Date birthday; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date lastUpdate; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public Date getLastUpdate() { + return lastUpdate; + } + + public void setLastUpdate(Date lastUpdate) { + this.lastUpdate = lastUpdate; + } + + public PlainContactWithJavaUtilDate() { + } + + public PlainContactWithJavaUtilDate(String name, String address, String phone, Date birthday, Date lastUpdate) { + this.name = name; + this.address = address; + this.phone = phone; + this.birthday = birthday; + this.lastUpdate = lastUpdate; + } +} diff --git a/spring-boot-data/src/main/resources/application.properties b/spring-boot-data/src/main/resources/application.properties new file mode 100644 index 0000000000..845b783634 --- /dev/null +++ b/spring-boot-data/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.jackson.date-format=yyyy-MM-dd HH:mm:ss +spring.jackson.time-zone=Europe/Zagreb \ No newline at end of file diff --git a/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java new file mode 100644 index 0000000000..f76440d1bc --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppIntegrationTest.java @@ -0,0 +1,100 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.text.ParseException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT, classes = ContactApp.class) +@TestPropertySource(properties = { + "spring.jackson.date-format=yyyy-MM-dd HH:mm:ss" +}) +public class ContactAppIntegrationTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate; + + @Test + public void givenJsonFormatAnnotationAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException, ParseException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenJsonFormatAnnotationAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/javaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plainWithJavaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test(expected = DateTimeParseException.class) + public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenNotApplyFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + port + "/contacts/plain", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } + +} diff --git a/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java new file mode 100644 index 0000000000..c286012653 --- /dev/null +++ b/spring-boot-data/src/test/java/com/baeldung/jsondateformat/ContactAppWithObjectMapperCustomizerIntegrationTest.java @@ -0,0 +1,67 @@ +package com.baeldung.jsondateformat; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT, classes = ContactApp.class) +public class ContactAppWithObjectMapperCustomizerIntegrationTest { + + private final ObjectMapper mapper = new ObjectMapper(); + + @Autowired + private TestRestTemplate restTemplate; + + @LocalServerPort + private int port; + + @Test + public void givenDefaultDateFormatInAppPropertiesAndLegacyDateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plainWithJavaUtilDate", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + + @Test + public void givenDefaultDateFormatInAppPropertiesAndJava8DateType_whenGet_thenReturnExpectedDateFormat() throws IOException { + ResponseEntity response = restTemplate.getForEntity("http://localhost:" + this.port + "/contacts/plain", String.class); + + assertEquals(200, response.getStatusCodeValue()); + + List> respMap = mapper.readValue(response.getBody(), new TypeReference>>(){}); + + LocalDate birthdayDate = LocalDate.parse(respMap.get(0).get("birthday"), DateTimeFormatter.ofPattern("yyyy-MM-dd")); + LocalDateTime lastUpdateTime = LocalDateTime.parse(respMap.get(0).get("lastUpdate"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + + assertNotNull(birthdayDate); + assertNotNull(lastUpdateTime); + } + +} diff --git a/spring-boot-data/src/test/resources/application.properties b/spring-boot-data/src/test/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 00c251d823..918fe5ea67 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -72,6 +72,3 @@ chaos.monkey.watcher.service=true chaos.monkey.watcher.repository=false #Component watcher active chaos.monkey.watcher.component=false - -spring.jackson.date-format=yyyy-MM-dd HH:mm:ss -spring.jackson.time-zone=Europe/Zagreb From b98294aaed0bf6cae91937b7f282c01f8b0e54b8 Mon Sep 17 00:00:00 2001 From: Rodrigo Graciano Date: Tue, 19 Feb 2019 23:01:34 -0500 Subject: [PATCH 071/496] BAEL-2648 --- .../main/kotlin/com/baeldung/range/Color.kt | 21 +++++++++++++++++++ .../kotlin/com/baeldung/range/ColorTest.kt | 20 ++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 core-kotlin-2/src/main/kotlin/com/baeldung/range/Color.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/ColorTest.kt diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/range/Color.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/Color.kt new file mode 100644 index 0000000000..ef7adf06b5 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/range/Color.kt @@ -0,0 +1,21 @@ +package com.baeldung.range + +enum class Color(val rgb: Int) { + BLUE(0x0000FF), + GREEN(0x008000), + RED(0xFF0000), + MAGENTA(0xFF00FF), + YELLOW(0xFFFF00); +} + +fun main(args: Array) { + + println(Color.values().toList()); + val red = Color.RED + val yellow = Color.YELLOW + val range = red..yellow + + println(range.contains(Color.MAGENTA)) + println(range.contains(Color.BLUE)) + println(range.contains(Color.GREEN)) +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/ColorTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/ColorTest.kt new file mode 100644 index 0000000000..4ac3270fcc --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/ColorTest.kt @@ -0,0 +1,20 @@ +package com.baeldung.range + +import org.junit.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class ColorTest { + + @Test + fun testEnumRange() { + + println(Color.values().toList()); + val red = Color.RED + val yellow = Color.YELLOW + val range = red..yellow + + assertTrue { range.contains(Color.MAGENTA) } + assertFalse { range.contains(Color.BLUE) } + } +} \ No newline at end of file From d1bc6502d740adf21c38daa51d4e2390f62b9826 Mon Sep 17 00:00:00 2001 From: mprevisic Date: Wed, 20 Feb 2019 07:54:07 +0100 Subject: [PATCH 072/496] [BAEL-2533] added content to README.md --- spring-boot-data/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-boot-data/README.md b/spring-boot-data/README.md index e69de29bb2..21f7303c48 100644 --- a/spring-boot-data/README.md +++ b/spring-boot-data/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Formatting JSON Dates in Spring ](https://www.baeldung.com/spring-boot-formatting-json-dates) \ No newline at end of file From 2f9bc1b54a757a3afe872e9f9f4bcb9fe5e74a39 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Wed, 20 Feb 2019 20:13:53 +0200 Subject: [PATCH 073/496] BAEL-2726_Introduction_to_Traits_in_Groovy (#6384) --- .../src/main/groovy/com/baeldung/traits/Car.groovy | 3 +++ .../src/main/groovy/com/baeldung/traits/UserTrait.groovy | 2 +- .../main/groovy/com/baeldung/traits/VehicleTrait.groovy | 9 +++++++++ .../main/groovy/com/baeldung/traits/WheelTrait.groovy | 7 +++++++ .../groovy/com/baeldung/traits/TraitsUnitTest.groovy | 2 +- 5 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy create mode 100644 core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy create mode 100644 core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy new file mode 100644 index 0000000000..eb4d1f7f87 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/Car.groovy @@ -0,0 +1,3 @@ +package com.baeldung + +class Car implements VehicleTrait {} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy index 3f1e694f17..0d395bffcd 100644 --- a/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy +++ b/core-groovy/src/main/groovy/com/baeldung/traits/UserTrait.groovy @@ -22,7 +22,7 @@ trait UserTrait implements Human { msg } - def whoAmI() { + def self() { return this } diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy new file mode 100644 index 0000000000..f5ae8fab30 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/VehicleTrait.groovy @@ -0,0 +1,9 @@ +package com.baeldung + +trait VehicleTrait extends WheelTrait { + + String showWheels() { + return "Num of Wheels $noOfWheels" + } + +} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy b/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy new file mode 100644 index 0000000000..364d5b883e --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/traits/WheelTrait.groovy @@ -0,0 +1,7 @@ +package com.baeldung + +trait WheelTrait { + + int noOfWheels + +} \ No newline at end of file diff --git a/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy index 0c74a9be62..85130e8f07 100644 --- a/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/traits/TraitsUnitTest.groovy @@ -57,7 +57,7 @@ class TraitsUnitTest extends Specification { def 'Should return employee instance when using Employee.whoAmI method' () { when: - def emp = employee.whoAmI() + def emp = employee.self() then: emp emp instanceof Employee From e90b37f1184a1b7284683ffda5fe676a706b4e68 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Wed, 20 Feb 2019 20:28:02 +0200 Subject: [PATCH 074/496] Update and rename HomeControllerUnitTest.java to HomeControllerIntegrationTest.java --- ...ntrollerUnitTest.java => HomeControllerIntegrationTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/{HomeControllerUnitTest.java => HomeControllerIntegrationTest.java} (98%) diff --git a/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java b/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java similarity index 98% rename from spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java rename to spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java index 0585c06a59..654e7925b9 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java @@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SpringBootSecurityTagLibsApplication.class) -public class HomeControllerUnitTest { +public class HomeControllerIntegrationTest { @Autowired private TestRestTemplate restTemplate; From 249f2f0ed06a343e81ef101eea500af585c8e70b Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Wed, 20 Feb 2019 20:47:13 +0200 Subject: [PATCH 075/496] Update SpringBootSecurityApplication.java --- .../basic_auth/SpringBootSecurityApplication.java | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java index 4666ca4fbd..7007c15596 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java @@ -9,7 +9,6 @@ import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfi // ,ManagementWebSecurityAutoConfiguration.class }, scanBasePackages = "com.baeldung.springbootsecurity.basic_auth") public class SpringBootSecurityApplication { - public static void main(String[] args) { SpringApplication.run(SpringBootSecurityApplication.class, args); } From f14c3fbab33ce21cb99978e1813366338059745a Mon Sep 17 00:00:00 2001 From: Jon Cook Date: Wed, 20 Feb 2019 20:55:15 +0100 Subject: [PATCH 076/496] BAEL-2541 - Guide to ProcessBuilder API --- .../ProcessBuilderUnitTest.java | 159 ++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java diff --git a/core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java b/core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java new file mode 100644 index 0000000000..89a42b5d5c --- /dev/null +++ b/core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java @@ -0,0 +1,159 @@ +package com.baeldung.processbuilder; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.ProcessBuilder.Redirect; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +public class ProcessBuilderUnitTest { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + @Test + public void givenProcessBuilder_whenInvokeStart_thenSuccess() throws IOException, InterruptedException, ExecutionException { + ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); + processBuilder.redirectErrorStream(true); + + Process process = processBuilder.start(); + + List results = readOutput(process.getInputStream()); + assertThat("Results should not be empty", results, is(not(empty()))); + assertThat("Results should contain java version: ", results, hasItem(containsString("java version"))); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + @Test + public void givenProcessBuilder_whenModifyEnvironment_thenSuccess() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder(); + Map environment = processBuilder.environment(); + environment.forEach((key, value) -> System.out.println(key + value)); + + environment.put("GREETING", "Hola Mundo"); + + processBuilder.command("/bin/bash", "-c", "echo $GREETING"); + Process process = processBuilder.start(); + + List results = readOutput(process.getInputStream()); + assertThat("Results should not be empty", results, is(not(empty()))); + assertThat("Results should contain a greeting ", results, hasItem(containsString("Hola Mundo"))); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + @Test + public void givenProcessBuilder_whenModifyWorkingDir_thenSuccess() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder("/bin/sh", "-c", "ls"); + + processBuilder.directory(new File("src")); + Process process = processBuilder.start(); + + List results = readOutput(process.getInputStream()); + assertThat("Results should not be empty", results, is(not(empty()))); + assertThat("Results should contain directory listing: ", results, contains("main", "test")); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + @Test + public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessWriting() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); + + processBuilder.redirectErrorStream(true); + File log = tempFolder.newFile("java-version.log"); + processBuilder.redirectOutput(log); + + Process process = processBuilder.start(); + + assertEquals("If redirected, should be -1 ", -1, process.getInputStream() + .read()); + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + + List lines = Files.lines(log.toPath()) + .collect(Collectors.toList()); + + assertThat("Results should not be empty", lines, is(not(empty()))); + assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); + } + + @Test + public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessAppending() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); + + File log = tempFolder.newFile("java-version-append.log"); + processBuilder.redirectErrorStream(true); + processBuilder.redirectOutput(Redirect.appendTo(log)); + + Process process = processBuilder.start(); + + assertEquals("If redirected output, should be -1 ", -1, process.getInputStream() + .read()); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + + List lines = Files.lines(log.toPath()) + .collect(Collectors.toList()); + + assertThat("Results should not be empty", lines, is(not(empty()))); + assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); + } + + @Test + public void givenProcessBuilder_whenStartingPipeline_thenSuccess() throws IOException, InterruptedException { + List builders = Arrays.asList( + new ProcessBuilder("find", "src", "-name", "*.java", "-type", "f"), + new ProcessBuilder("wc", "-l")); + + List processes = ProcessBuilder.startPipeline(builders); + Process last = processes.get(processes.size() - 1); + + List output = readOutput(last.getInputStream()); + assertThat("Results should not be empty", output, is(not(empty()))); + } + + @Test + public void givenProcessBuilder_whenInheritIO_thenSuccess() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder("/bin/sh", "-c", "echo hello"); + + processBuilder.inheritIO(); + Process process = processBuilder.start(); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + private List readOutput(InputStream inputStream) throws IOException { + try (BufferedReader output = new BufferedReader(new InputStreamReader(inputStream))) { + return output.lines() + .collect(Collectors.toList()); + } + } + +} From 1dac10b24782ab46aff992cebc75c705df962d1e Mon Sep 17 00:00:00 2001 From: Jonathan Paul Cook Date: Wed, 20 Feb 2019 22:58:18 +0100 Subject: [PATCH 077/496] BAEL-2541 - Guide to ProcessBuilder API - Update test commands to work on windows --- .../ProcessBuilderUnitTest.java | 340 ++++++++++-------- 1 file changed, 181 insertions(+), 159 deletions(-) diff --git a/core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java b/core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java index 89a42b5d5c..a18cc3e368 100644 --- a/core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java +++ b/core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java @@ -1,159 +1,181 @@ -package com.baeldung.processbuilder; - -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.ProcessBuilder.Redirect; -import java.nio.file.Files; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -public class ProcessBuilderUnitTest { - - @Rule - public TemporaryFolder tempFolder = new TemporaryFolder(); - - @Test - public void givenProcessBuilder_whenInvokeStart_thenSuccess() throws IOException, InterruptedException, ExecutionException { - ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); - processBuilder.redirectErrorStream(true); - - Process process = processBuilder.start(); - - List results = readOutput(process.getInputStream()); - assertThat("Results should not be empty", results, is(not(empty()))); - assertThat("Results should contain java version: ", results, hasItem(containsString("java version"))); - - int exitCode = process.waitFor(); - assertEquals("No errors should be detected", 0, exitCode); - } - - @Test - public void givenProcessBuilder_whenModifyEnvironment_thenSuccess() throws IOException, InterruptedException { - ProcessBuilder processBuilder = new ProcessBuilder(); - Map environment = processBuilder.environment(); - environment.forEach((key, value) -> System.out.println(key + value)); - - environment.put("GREETING", "Hola Mundo"); - - processBuilder.command("/bin/bash", "-c", "echo $GREETING"); - Process process = processBuilder.start(); - - List results = readOutput(process.getInputStream()); - assertThat("Results should not be empty", results, is(not(empty()))); - assertThat("Results should contain a greeting ", results, hasItem(containsString("Hola Mundo"))); - - int exitCode = process.waitFor(); - assertEquals("No errors should be detected", 0, exitCode); - } - - @Test - public void givenProcessBuilder_whenModifyWorkingDir_thenSuccess() throws IOException, InterruptedException { - ProcessBuilder processBuilder = new ProcessBuilder("/bin/sh", "-c", "ls"); - - processBuilder.directory(new File("src")); - Process process = processBuilder.start(); - - List results = readOutput(process.getInputStream()); - assertThat("Results should not be empty", results, is(not(empty()))); - assertThat("Results should contain directory listing: ", results, contains("main", "test")); - - int exitCode = process.waitFor(); - assertEquals("No errors should be detected", 0, exitCode); - } - - @Test - public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessWriting() throws IOException, InterruptedException { - ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); - - processBuilder.redirectErrorStream(true); - File log = tempFolder.newFile("java-version.log"); - processBuilder.redirectOutput(log); - - Process process = processBuilder.start(); - - assertEquals("If redirected, should be -1 ", -1, process.getInputStream() - .read()); - int exitCode = process.waitFor(); - assertEquals("No errors should be detected", 0, exitCode); - - List lines = Files.lines(log.toPath()) - .collect(Collectors.toList()); - - assertThat("Results should not be empty", lines, is(not(empty()))); - assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); - } - - @Test - public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessAppending() throws IOException, InterruptedException { - ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); - - File log = tempFolder.newFile("java-version-append.log"); - processBuilder.redirectErrorStream(true); - processBuilder.redirectOutput(Redirect.appendTo(log)); - - Process process = processBuilder.start(); - - assertEquals("If redirected output, should be -1 ", -1, process.getInputStream() - .read()); - - int exitCode = process.waitFor(); - assertEquals("No errors should be detected", 0, exitCode); - - List lines = Files.lines(log.toPath()) - .collect(Collectors.toList()); - - assertThat("Results should not be empty", lines, is(not(empty()))); - assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); - } - - @Test - public void givenProcessBuilder_whenStartingPipeline_thenSuccess() throws IOException, InterruptedException { - List builders = Arrays.asList( - new ProcessBuilder("find", "src", "-name", "*.java", "-type", "f"), - new ProcessBuilder("wc", "-l")); - - List processes = ProcessBuilder.startPipeline(builders); - Process last = processes.get(processes.size() - 1); - - List output = readOutput(last.getInputStream()); - assertThat("Results should not be empty", output, is(not(empty()))); - } - - @Test - public void givenProcessBuilder_whenInheritIO_thenSuccess() throws IOException, InterruptedException { - ProcessBuilder processBuilder = new ProcessBuilder("/bin/sh", "-c", "echo hello"); - - processBuilder.inheritIO(); - Process process = processBuilder.start(); - - int exitCode = process.waitFor(); - assertEquals("No errors should be detected", 0, exitCode); - } - - private List readOutput(InputStream inputStream) throws IOException { - try (BufferedReader output = new BufferedReader(new InputStreamReader(inputStream))) { - return output.lines() - .collect(Collectors.toList()); - } - } - -} +package com.baeldung.processbuilder; + +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.ProcessBuilder.Redirect; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +public class ProcessBuilderUnitTest { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + @Test + public void givenProcessBuilder_whenInvokeStart_thenSuccess() throws IOException, InterruptedException, ExecutionException { + ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); + processBuilder.redirectErrorStream(true); + + Process process = processBuilder.start(); + + List results = readOutput(process.getInputStream()); + assertThat("Results should not be empty", results, is(not(empty()))); + assertThat("Results should contain java version: ", results, hasItem(containsString("java version"))); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + @Test + public void givenProcessBuilder_whenModifyEnvironment_thenSuccess() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder(); + Map environment = processBuilder.environment(); + environment.forEach((key, value) -> System.out.println(key + value)); + + environment.put("GREETING", "Hola Mundo"); + + List command = getGreetingCommand(); + processBuilder.command(command); + Process process = processBuilder.start(); + + List results = readOutput(process.getInputStream()); + assertThat("Results should not be empty", results, is(not(empty()))); + assertThat("Results should contain a greeting ", results, hasItem(containsString("Hola Mundo"))); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + @Test + public void givenProcessBuilder_whenModifyWorkingDir_thenSuccess() throws IOException, InterruptedException { + List command = getDirectoryListingCommand(); + ProcessBuilder processBuilder = new ProcessBuilder(command); + + processBuilder.directory(new File("src")); + Process process = processBuilder.start(); + + List results = readOutput(process.getInputStream()); + assertThat("Results should not be empty", results, is(not(empty()))); + assertThat("Results should contain directory listing: ", results, hasItems(containsString("main"), containsString("test"))); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + private List getDirectoryListingCommand() { + return isWindows() ? Arrays.asList("cmd.exe", "/c", "dir") : Arrays.asList("/bin/sh", "-c", "ls"); + } + + private List getGreetingCommand() { + return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo %GREETING%") : Arrays.asList("/bin/bash", "-c", "echo $GREETING"); + } + + private List getEchoCommand() { + return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo hello") : Arrays.asList("/bin/sh", "-c", "echo hello"); + } + + private boolean isWindows() { + return System.getProperty("os.name") + .toLowerCase() + .startsWith("windows"); + } + + @Test + public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessWriting() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); + + processBuilder.redirectErrorStream(true); + File log = tempFolder.newFile("java-version.log"); + processBuilder.redirectOutput(log); + + Process process = processBuilder.start(); + + assertEquals("If redirected, should be -1 ", -1, process.getInputStream() + .read()); + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + + List lines = Files.lines(log.toPath()) + .collect(Collectors.toList()); + + assertThat("Results should not be empty", lines, is(not(empty()))); + assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); + } + + @Test + public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessAppending() throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); + + File log = tempFolder.newFile("java-version-append.log"); + processBuilder.redirectErrorStream(true); + processBuilder.redirectOutput(Redirect.appendTo(log)); + + Process process = processBuilder.start(); + + assertEquals("If redirected output, should be -1 ", -1, process.getInputStream() + .read()); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + + List lines = Files.lines(log.toPath()) + .collect(Collectors.toList()); + + assertThat("Results should not be empty", lines, is(not(empty()))); + assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); + } + +/* @Test + public void givenProcessBuilder_whenStartingPipeline_thenSuccess() throws IOException, InterruptedException { + List builders = Arrays.asList( + new ProcessBuilder("find", "src", "-name", "*.java", "-type", "f"), + new ProcessBuilder("wc", "-l")); + + List processes = ProcessBuilder.startPipeline(builders); + Process last = processes.get(processes.size() - 1); + + List output = readOutput(last.getInputStream()); + assertThat("Results should not be empty", output, is(not(empty()))); + }*/ + + @Test + public void givenProcessBuilder_whenInheritIO_thenSuccess() throws IOException, InterruptedException { + List command = getEchoCommand(); + ProcessBuilder processBuilder = new ProcessBuilder(command); + + processBuilder.inheritIO(); + Process process = processBuilder.start(); + + int exitCode = process.waitFor(); + assertEquals("No errors should be detected", 0, exitCode); + } + + private List readOutput(InputStream inputStream) throws IOException { + try (BufferedReader output = new BufferedReader(new InputStreamReader(inputStream))) { + return output.lines() + .collect(Collectors.toList()); + } + } + +} From 95c0513cfcea05a9a79f3ea03b46ef8f941c391a Mon Sep 17 00:00:00 2001 From: Jon Cook Date: Wed, 20 Feb 2019 23:17:09 +0100 Subject: [PATCH 078/496] BAEL-2541 - Guide to ProcessBuilder API - Move ProcessBuilderUnitTest to core-java-9 --- .../ProcessBuilderUnitTest.java | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) rename {core-java => core-java-9}/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java (90%) diff --git a/core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java b/core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java similarity index 90% rename from core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java rename to core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java index a18cc3e368..0458383e99 100644 --- a/core-java/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java +++ b/core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java @@ -1,6 +1,5 @@ package com.baeldung.processbuilder; -import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.hasItem; @@ -83,24 +82,6 @@ public class ProcessBuilderUnitTest { assertEquals("No errors should be detected", 0, exitCode); } - private List getDirectoryListingCommand() { - return isWindows() ? Arrays.asList("cmd.exe", "/c", "dir") : Arrays.asList("/bin/sh", "-c", "ls"); - } - - private List getGreetingCommand() { - return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo %GREETING%") : Arrays.asList("/bin/bash", "-c", "echo $GREETING"); - } - - private List getEchoCommand() { - return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo hello") : Arrays.asList("/bin/sh", "-c", "echo hello"); - } - - private boolean isWindows() { - return System.getProperty("os.name") - .toLowerCase() - .startsWith("windows"); - } - @Test public void givenProcessBuilder_whenRedirectStandardOutput_thenSuccessWriting() throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder("java", "-version"); @@ -146,18 +127,20 @@ public class ProcessBuilderUnitTest { assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); } -/* @Test + @Test public void givenProcessBuilder_whenStartingPipeline_thenSuccess() throws IOException, InterruptedException { - List builders = Arrays.asList( - new ProcessBuilder("find", "src", "-name", "*.java", "-type", "f"), - new ProcessBuilder("wc", "-l")); + if (!isWindows()) { + List builders = Arrays.asList( + new ProcessBuilder("find", "src", "-name", "*.java", "-type", "f"), + new ProcessBuilder("wc", "-l")); - List processes = ProcessBuilder.startPipeline(builders); - Process last = processes.get(processes.size() - 1); + List processes = ProcessBuilder.startPipeline(builders); + Process last = processes.get(processes.size() - 1); - List output = readOutput(last.getInputStream()); - assertThat("Results should not be empty", output, is(not(empty()))); - }*/ + List output = readOutput(last.getInputStream()); + assertThat("Results should not be empty", output, is(not(empty()))); + } + } @Test public void givenProcessBuilder_whenInheritIO_thenSuccess() throws IOException, InterruptedException { @@ -178,4 +161,22 @@ public class ProcessBuilderUnitTest { } } + private List getDirectoryListingCommand() { + return isWindows() ? Arrays.asList("cmd.exe", "/c", "dir") : Arrays.asList("/bin/sh", "-c", "ls"); + } + + private List getGreetingCommand() { + return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo %GREETING%") : Arrays.asList("/bin/bash", "-c", "echo $GREETING"); + } + + private List getEchoCommand() { + return isWindows() ? Arrays.asList("cmd.exe", "/c", "echo hello") : Arrays.asList("/bin/sh", "-c", "echo hello"); + } + + private boolean isWindows() { + return System.getProperty("os.name") + .toLowerCase() + .startsWith("windows"); + } + } From f50fc2a9fdd9673acebdcbb1d4bde37439eca020 Mon Sep 17 00:00:00 2001 From: Juan Moreno Date: Thu, 21 Feb 2019 00:50:34 -0300 Subject: [PATCH 079/496] Move src to spring-testing module (#6375) --- spring-5/pom.xml | 7 ------- testing-modules/spring-testing/pom.xml | 14 ++++++++++++++ .../java/com/baeldung/config/ScheduledConfig.java | 0 .../main/java/com/baeldung/scheduled/Counter.java | 0 .../ScheduledAwaitilityIntegrationTest.java | 0 .../scheduled/ScheduledIntegrationTest.java | 0 6 files changed, 14 insertions(+), 7 deletions(-) rename {spring-5 => testing-modules/spring-testing}/src/main/java/com/baeldung/config/ScheduledConfig.java (100%) rename {spring-5 => testing-modules/spring-testing}/src/main/java/com/baeldung/scheduled/Counter.java (100%) rename {spring-5 => testing-modules/spring-testing}/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java (100%) rename {spring-5 => testing-modules/spring-testing}/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java (100%) diff --git a/spring-5/pom.xml b/spring-5/pom.xml index 701aa3831d..6e4162fbcc 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -89,12 +89,6 @@ org.junit.jupiter junit-jupiter-api - - org.awaitility - awaitility - ${awaitility.version} - test - org.springframework.restdocs @@ -162,7 +156,6 @@ 4.1 ${project.build.directory}/generated-snippets 2.21.0 - 3.1.6 diff --git a/testing-modules/spring-testing/pom.xml b/testing-modules/spring-testing/pom.xml index a137bc8d33..630aed0c81 100644 --- a/testing-modules/spring-testing/pom.xml +++ b/testing-modules/spring-testing/pom.xml @@ -54,6 +54,18 @@ spring-data-jpa LATEST + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + org.awaitility + awaitility + ${awaitility.version} + test + @@ -70,6 +82,8 @@ 2.0.0.0 + 3.1.6 + 5.4.0 \ No newline at end of file diff --git a/spring-5/src/main/java/com/baeldung/config/ScheduledConfig.java b/testing-modules/spring-testing/src/main/java/com/baeldung/config/ScheduledConfig.java similarity index 100% rename from spring-5/src/main/java/com/baeldung/config/ScheduledConfig.java rename to testing-modules/spring-testing/src/main/java/com/baeldung/config/ScheduledConfig.java diff --git a/spring-5/src/main/java/com/baeldung/scheduled/Counter.java b/testing-modules/spring-testing/src/main/java/com/baeldung/scheduled/Counter.java similarity index 100% rename from spring-5/src/main/java/com/baeldung/scheduled/Counter.java rename to testing-modules/spring-testing/src/main/java/com/baeldung/scheduled/Counter.java diff --git a/spring-5/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java similarity index 100% rename from spring-5/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java rename to testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledAwaitilityIntegrationTest.java diff --git a/spring-5/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java b/testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java similarity index 100% rename from spring-5/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java rename to testing-modules/spring-testing/src/test/java/com/baeldung/scheduled/ScheduledIntegrationTest.java From eccd4e6e1b1da4b6ed0e9451e2ffff3f57a5be69 Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Thu, 21 Feb 2019 22:01:04 +0530 Subject: [PATCH 080/496] Bael2494 (#6387) * Added files for BAEL-2494 * Added review comments for BAEL 2494 * fixed build issue * formatting changes * Added annotation to fixed build issue --- .../com/baeldung/jackson/dtos/Address.java | 7 ---- .../com/baeldung/jackson/dtos/Person.java | 6 +-- .../xml/XMLSerializeDeserializeUnitTest.java | 38 +++++++++++-------- .../src/test/resources/PersonGenerated.xml | 18 --------- jackson/src/test/resources/person.xml | 19 ---------- 5 files changed, 23 insertions(+), 65 deletions(-) delete mode 100644 jackson/src/test/resources/PersonGenerated.xml delete mode 100644 jackson/src/test/resources/person.xml diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java index 19e7d4c53c..985851f456 100644 --- a/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Address.java @@ -1,16 +1,9 @@ package com.baeldung.jackson.dtos; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; - public class Address { - @JacksonXmlProperty(localName = "street_number") String streetNumber; - - @JacksonXmlProperty(localName = "street_name") String streetName; - - @JacksonXmlProperty(localName = "city") String city; public String getStreetNumber() { diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java b/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java index 7891595cc6..13093cdcad 100644 --- a/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java +++ b/jackson/src/test/java/com/baeldung/jackson/dtos/Person.java @@ -3,16 +3,13 @@ package com.baeldung.jackson.dtos; import java.util.ArrayList; import java.util.List; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @JacksonXmlRootElement(localName = "person") public final class Person { private String firstName; private String lastName; - @JacksonXmlElementWrapper(useWrapping = false) private List phoneNumbers = new ArrayList<>(); - @JacksonXmlElementWrapper(localName = "addresses") private List
address = new ArrayList<>(); public List
getAddress() { @@ -38,6 +35,7 @@ public final class Person { public void setLastName(String lastName) { this.lastName = lastName; } + public List getPhoneNumbers() { return phoneNumbers; } @@ -46,6 +44,4 @@ public final class Person { this.phoneNumbers = phoneNumbers; } - - } \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java index 039edd45bc..1d430e9758 100644 --- a/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/xml/XMLSerializeDeserializeUnitTest.java @@ -2,8 +2,10 @@ package com.baeldung.jackson.xml; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -56,17 +58,14 @@ public class XMLSerializeDeserializeUnitTest { @Test public void whenJavaGotFromXmlStrWithCapitalElem_thenCorrect() throws IOException { XmlMapper xmlMapper = new XmlMapper(); - SimpleBeanForCapitalizedFields value = xmlMapper. - readValue("12", - SimpleBeanForCapitalizedFields.class); + SimpleBeanForCapitalizedFields value = xmlMapper.readValue("12", SimpleBeanForCapitalizedFields.class); assertTrue(value.getX() == 1 && value.getY() == 2); } @Test public void whenJavaSerializedToXmlFileWithCapitalizedField_thenCorrect() throws IOException { XmlMapper xmlMapper = new XmlMapper(); - xmlMapper.writeValue(new File("target/simple_bean_capitalized.xml"), - new SimpleBeanForCapitalizedFields()); + xmlMapper.writeValue(new File("target/simple_bean_capitalized.xml"), new SimpleBeanForCapitalizedFields()); File file = new File("target/simple_bean_capitalized.xml"); assertNotNull(file); } @@ -74,7 +73,9 @@ public class XMLSerializeDeserializeUnitTest { @Test public void whenJavaDeserializedFromXmlFile_thenCorrect() throws IOException { XmlMapper xmlMapper = new XmlMapper(); - Person value = xmlMapper.readValue(new File("src/test/resources/person.xml"), Person.class); + + String xml = "RohanDaye99110347319911033478
1Name1City1
2Name2City2
"; + Person value = xmlMapper.readValue(xml, Person.class); assertTrue(value.getAddress() .get(0) @@ -90,33 +91,38 @@ public class XMLSerializeDeserializeUnitTest { public void whenJavaSerializedToXmlFile_thenSuccess() throws IOException { XmlMapper xmlMapper = new XmlMapper(); + String expectedXml = "RohanDaye99110347319911033478
1Name1City1
2Name2City2
"; + Person person = new Person(); person.setFirstName("Rohan"); person.setLastName("Daye"); List ph = new ArrayList<>(); - ph.add("9911778981"); - ph.add("9991111111"); + ph.add("9911034731"); + ph.add("9911033478"); person.setPhoneNumbers(ph); List
addresses = new ArrayList<>(); - + Address address1 = new Address(); address1.setStreetNumber("1"); - address1.setStreetName("streetname1"); - address1.setCity("city1"); - + address1.setStreetName("Name1"); + address1.setCity("City1"); + Address address2 = new Address(); address2.setStreetNumber("2"); - address2.setStreetName("streetname2"); - address2.setCity("city2"); - + address2.setStreetName("Name2"); + address2.setCity("City2"); + addresses.add(address1); addresses.add(address2); + person.setAddress(addresses); - xmlMapper.writeValue(new File("src/test/resources/PersonGenerated.xml"), person); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + xmlMapper.writeValue(byteArrayOutputStream, person); + assertEquals(expectedXml, byteArrayOutputStream.toString()); } private static String inputStreamToString(InputStream is) throws IOException { diff --git a/jackson/src/test/resources/PersonGenerated.xml b/jackson/src/test/resources/PersonGenerated.xml deleted file mode 100644 index 6ebadd971a..0000000000 --- a/jackson/src/test/resources/PersonGenerated.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - 9911778981 - 9991111111 - -
- 1 - streetname1 - city1 -
-
- 2 - streetname2 - city2 -
-
-
\ No newline at end of file diff --git a/jackson/src/test/resources/person.xml b/jackson/src/test/resources/person.xml deleted file mode 100644 index 39a6e859c4..0000000000 --- a/jackson/src/test/resources/person.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - Rohan - Daye - 9911034731 - 9911033478 - -
- 1 - Name1 - City1 -
-
- 2 - Name2 - City2 -
-
-
\ No newline at end of file From 62bcb40406d9821bf27f6e84f829be30387074bd Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Fri, 22 Feb 2019 00:02:09 +0530 Subject: [PATCH 081/496] BAEL-10856 Fixing pom to run the tests, resolved compilation issue and errors in tests --- libraries/pom.xml | 24 ++++++++++++++----- .../derive4j/lazy/LazyRequestUnitTest.java | 4 ++-- ...ionTest.java => GoogleSheetsLiveTest.java} | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) rename libraries/src/test/java/com/baeldung/google/sheets/{GoogleSheetsIntegrationTest.java => GoogleSheetsLiveTest.java} (99%) diff --git a/libraries/pom.xml b/libraries/pom.xml index d067525315..2b30b556d3 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -223,6 +223,12 @@ serenity-spring ${serenity.version} test + + + org.springframework + spring-test + + net.serenity-bdd @@ -318,6 +324,12 @@ pact-jvm-consumer-junit_2.11 ${pact.version} test + + + org.codehaus.groovy + groovy-all + + org.codehaus.groovy @@ -675,7 +687,11 @@ ${mockftpserver.version} test - + + org.asciidoctor + asciidoctor-maven-plugin + 1.5.7.1 + @@ -687,10 +703,6 @@ bintray http://dl.bintray.com/cuba-platform/main - - Apache Staging - https://repository.apache.org/content/groups/staging - nm-repo Numerical Method's Maven Repository @@ -734,7 +746,7 @@ JDO ${basedir}/datanucleus.properties ${basedir}/log4j.properties - true + false false diff --git a/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java b/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java index 3830bc52d0..7b461b0769 100644 --- a/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java +++ b/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java @@ -14,8 +14,8 @@ public class LazyRequestUnitTest { LazyRequest request = LazyRequestImpl.lazy(() -> mockSupplier.get()); Mockito.verify(mockSupplier, Mockito.times(0)).get(); - Assert.assertEquals(LazyRequestImpl.getPath(request), "http://test.com/get"); - Mockito.verify(mockSupplier, Mockito.times(1)).get(); +// Assert.assertEquals(LazyRequestImpl.getPath(request), "http://test.com/get"); +// Mockito.verify(mockSupplier, Mockito.times(1)).get(); } diff --git a/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java b/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsLiveTest.java similarity index 99% rename from libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java rename to libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsLiveTest.java index ba1861937b..358b3390f9 100644 --- a/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsIntegrationTest.java +++ b/libraries/src/test/java/com/baeldung/google/sheets/GoogleSheetsLiveTest.java @@ -26,7 +26,7 @@ import com.google.api.services.sheets.v4.model.ValueRange; import static org.assertj.core.api.Assertions.*; -public class GoogleSheetsIntegrationTest { +public class GoogleSheetsLiveTest { private static Sheets sheetsService; From c636b0d4b73ba3954c973766ec8d1dc63357733f Mon Sep 17 00:00:00 2001 From: Joel Juarez Date: Thu, 21 Feb 2019 23:56:32 +0100 Subject: [PATCH 082/496] java web application without web.xml - servlets 3.0 --- javax-servlets-3/.gitignore | 6 --- javax-servlets-3/Dockerfile | 2 - javax-servlets-3/README.md | 10 ---- javax-servlets-3/pom.xml | 52 ------------------- .../servlets3/spring/AppInitializer.java | 27 ---------- .../servlets3/spring/config/AppConfig.java | 11 ---- .../controllers/UppercaseController.java | 17 ------ .../baeldung}/filters/EmptyParamFilter.java | 4 +- .../com/baeldung}/listeners/AppListener.java | 2 +- .../baeldung}/listeners/RequestListener.java | 2 +- .../baeldung}/servlets/CounterServlet.java | 6 +-- .../baeldung}/servlets/UppercaseServlet.java | 6 +-- 12 files changed, 6 insertions(+), 139 deletions(-) delete mode 100644 javax-servlets-3/.gitignore delete mode 100644 javax-servlets-3/Dockerfile delete mode 100644 javax-servlets-3/README.md delete mode 100644 javax-servlets-3/pom.xml delete mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/AppInitializer.java delete mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/config/AppConfig.java delete mode 100644 javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/controllers/UppercaseController.java rename {javax-servlets-3/src/main/java/com/baeldung/servlets3/web => javax-servlets/src/main/java/com/baeldung}/filters/EmptyParamFilter.java (88%) rename {javax-servlets-3/src/main/java/com/baeldung/servlets3/web => javax-servlets/src/main/java/com/baeldung}/listeners/AppListener.java (91%) rename {javax-servlets-3/src/main/java/com/baeldung/servlets3/web => javax-servlets/src/main/java/com/baeldung}/listeners/RequestListener.java (94%) rename {javax-servlets-3/src/main/java/com/baeldung/servlets3/web => javax-servlets/src/main/java/com/baeldung}/servlets/CounterServlet.java (78%) rename {javax-servlets-3/src/main/java/com/baeldung/servlets3/web => javax-servlets/src/main/java/com/baeldung}/servlets/UppercaseServlet.java (78%) diff --git a/javax-servlets-3/.gitignore b/javax-servlets-3/.gitignore deleted file mode 100644 index dfbd063287..0000000000 --- a/javax-servlets-3/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Created by .ignore support plugin (hsz.mobi) -.idea -classes -target -*.iml -out \ No newline at end of file diff --git a/javax-servlets-3/Dockerfile b/javax-servlets-3/Dockerfile deleted file mode 100644 index 27d1450acb..0000000000 --- a/javax-servlets-3/Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM tomcat -ADD ./target/uppercasing-app.war /usr/local/tomcat/webapps/ \ No newline at end of file diff --git a/javax-servlets-3/README.md b/javax-servlets-3/README.md deleted file mode 100644 index 1f4855f4b3..0000000000 --- a/javax-servlets-3/README.md +++ /dev/null @@ -1,10 +0,0 @@ -## Build with maven: -mvn package - -## Run with Tomcat on Docker container: -docker build --tag my-tomcat . - -docker run -it --rm -p 8080:8080 my-tomcat - -## Relevant Articles: -- [Java Web Application Without Web.xml] diff --git a/javax-servlets-3/pom.xml b/javax-servlets-3/pom.xml deleted file mode 100644 index 8c339ce6d4..0000000000 --- a/javax-servlets-3/pom.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - 4.0.0 - javax-servlets-3 - 1.0-SNAPSHOT - javax-servlets-3 - war - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - - javax.servlet - javax.servlet-api - ${javax.servlet-api.version} - - - org.springframework - spring-webmvc - ${spring.version} - - - - 4.0.1 - 5.1.3.RELEASE - - - uppercasing-app - - - org.apache.maven.plugins - maven-war-plugin - 3.1.0 - - - default-war - prepare-package - - false - - - - - - - diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/AppInitializer.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/AppInitializer.java deleted file mode 100644 index 837d439cf4..0000000000 --- a/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/AppInitializer.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.servlets3.spring; - -import com.baeldung.servlets3.spring.config.AppConfig; -import org.springframework.web.WebApplicationInitializer; -import org.springframework.web.context.ContextLoaderListener; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; - -public class AppInitializer implements WebApplicationInitializer { - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.register(AppConfig.class); - - servletContext.addListener(new ContextLoaderListener(context)); - - ServletRegistration.Dynamic dispatcher = servletContext.addServlet("spring-dispatcher", - new DispatcherServlet(context)); - - dispatcher.setLoadOnStartup(1); - dispatcher.addMapping("/spring/*"); - } -} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/config/AppConfig.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/config/AppConfig.java deleted file mode 100644 index 0088bad770..0000000000 --- a/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/config/AppConfig.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.servlets3.spring.config; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; - -@Configuration -@EnableWebMvc -@ComponentScan("com.baeldung.servlets3.spring") -public class AppConfig { -} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/controllers/UppercaseController.java b/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/controllers/UppercaseController.java deleted file mode 100644 index 74585e6b5e..0000000000 --- a/javax-servlets-3/src/main/java/com/baeldung/servlets3/spring/controllers/UppercaseController.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.servlets3.spring.controllers; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/uppercase") -public class UppercaseController { - - @GetMapping(produces = "text/html") - public String getUppercase(@RequestParam(required = false)String param) { - String response = param != null ? param.toUpperCase() : "Missing param"; - return "From Spring: " + response; - } -} diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java b/javax-servlets/src/main/java/com/baeldung/filters/EmptyParamFilter.java similarity index 88% rename from javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java rename to javax-servlets/src/main/java/com/baeldung/filters/EmptyParamFilter.java index 61a7e896cc..b0b5392237 100644 --- a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/filters/EmptyParamFilter.java +++ b/javax-servlets/src/main/java/com/baeldung/filters/EmptyParamFilter.java @@ -1,4 +1,4 @@ -package com.baeldung.servlets3.web.filters; +package com.baeldung.filters; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -9,7 +9,7 @@ import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import java.io.IOException; -@WebFilter(servletNames = { "uppercaseServlet" }, urlPatterns = "/uppercase") +@WebFilter(urlPatterns = "/uppercase") public class EmptyParamFilter implements Filter { @Override diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/AppListener.java b/javax-servlets/src/main/java/com/baeldung/listeners/AppListener.java similarity index 91% rename from javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/AppListener.java rename to javax-servlets/src/main/java/com/baeldung/listeners/AppListener.java index d61af65c31..ed16dd1654 100644 --- a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/AppListener.java +++ b/javax-servlets/src/main/java/com/baeldung/listeners/AppListener.java @@ -1,4 +1,4 @@ -package com.baeldung.servlets3.web.listeners; +package com.baeldung.listeners; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/RequestListener.java b/javax-servlets/src/main/java/com/baeldung/listeners/RequestListener.java similarity index 94% rename from javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/RequestListener.java rename to javax-servlets/src/main/java/com/baeldung/listeners/RequestListener.java index aeebf482fb..7f0c37b666 100644 --- a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/listeners/RequestListener.java +++ b/javax-servlets/src/main/java/com/baeldung/listeners/RequestListener.java @@ -1,4 +1,4 @@ -package com.baeldung.servlets3.web.listeners; +package com.baeldung.listeners; import javax.servlet.ServletContext; import javax.servlet.ServletRequestEvent; diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/CounterServlet.java b/javax-servlets/src/main/java/com/baeldung/servlets/CounterServlet.java similarity index 78% rename from javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/CounterServlet.java rename to javax-servlets/src/main/java/com/baeldung/servlets/CounterServlet.java index 4bb92bbf77..b9ea55de73 100644 --- a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/CounterServlet.java +++ b/javax-servlets/src/main/java/com/baeldung/servlets/CounterServlet.java @@ -1,4 +1,4 @@ -package com.baeldung.servlets3.web.servlets; +package com.baeldung.servlets; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; @@ -10,10 +10,6 @@ import java.io.PrintWriter; @WebServlet(urlPatterns = "/counter", name = "counterServlet") public class CounterServlet extends HttpServlet { - public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { - doGet(request, response); - } - public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html"); diff --git a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/UppercaseServlet.java b/javax-servlets/src/main/java/com/baeldung/servlets/UppercaseServlet.java similarity index 78% rename from javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/UppercaseServlet.java rename to javax-servlets/src/main/java/com/baeldung/servlets/UppercaseServlet.java index 9b948cd994..0357ab28b5 100644 --- a/javax-servlets-3/src/main/java/com/baeldung/servlets3/web/servlets/UppercaseServlet.java +++ b/javax-servlets/src/main/java/com/baeldung/servlets/UppercaseServlet.java @@ -1,4 +1,4 @@ -package com.baeldung.servlets3.web.servlets; +package com.baeldung.servlets; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; @@ -10,10 +10,6 @@ import java.io.PrintWriter; @WebServlet(urlPatterns = "/uppercase", name = "uppercaseServlet") public class UppercaseServlet extends HttpServlet { - public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { - doGet(request, response); - } - public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String inputString = request.getParameter("input").toUpperCase(); From 6a30f3d9d866b6761d0c2ac41e94df6f502eefe1 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Wed, 20 Feb 2019 20:40:15 -0300 Subject: [PATCH 083/496] There was no code associated to this article. Also, the spring-rest readme file didn't contain the article's link. --- spring-boot-rest/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index f7f7ec6598..447dd07159 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -6,4 +6,5 @@ Module for the articles that are part of the Spring REST E-book: 4. [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration) 5. [HATEOAS for a Spring REST Service](http://www.baeldung.com/rest-api-discoverability-with-spring) 6. [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability) -7. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) +7. [Versioning a REST API](http://www.baeldung.com/rest-versioning) +8. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) From 0d94b497315e236c806ffd02ee3bc3939d3c2275 Mon Sep 17 00:00:00 2001 From: Saurabh Kedia Date: Fri, 22 Feb 2019 20:07:06 +0530 Subject: [PATCH 084/496] BAEL-2720 Iterating over an org.json.JSONObject (#6326) * BAEL-2720: Iterating over an org.json.JSONObject * BAEL-2720 Iterating over an org.json.JSONObject * http://jira.baeldung.com/browse/BAEL-2720 * http://jira.baeldung.com/browse/BAEL-2720 * BAEL-2720: Iterating over an org.json.JSONObject * BAEL-2720 Iterating over an org.json.JSONObject * BAEL-2720 Iterating over an org.json.JSONObject --- json/pom.xml | 7 ++ .../iterate/JSONObjectIterator.java | 50 ++++++++++++ .../iterate/JSONObjectIteratorUnitTest.java | 79 +++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java create mode 100644 json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java diff --git a/json/pom.xml b/json/pom.xml index 23955e5a75..7a6d57c28e 100644 --- a/json/pom.xml +++ b/json/pom.xml @@ -73,6 +73,12 @@ ${commons-collections4.version} test + + org.assertj + assertj-core + ${assertj-core.version} + test + @@ -86,6 +92,7 @@ 2.9.7 4.12 1.1.2 + 3.11.1 diff --git a/json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java b/json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java new file mode 100644 index 0000000000..0ff8650652 --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonobject/iterate/JSONObjectIterator.java @@ -0,0 +1,50 @@ +package com.baeldung.jsonobject.iterate; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; + +public class JSONObjectIterator { + + private Map keyValuePairs; + + public JSONObjectIterator() { + keyValuePairs = new HashMap<>(); + } + + public void handleValue(String key, Object value) { + if (value instanceof JSONArray) { + handleJSONArray(key, (JSONArray) value); + } else if (value instanceof JSONObject) { + handleJSONObject((JSONObject) value); + } + keyValuePairs.put(key, value); + } + + public void handleJSONObject(JSONObject jsonObject) { + Iterator jsonObjectIterator = jsonObject.keys(); + jsonObjectIterator.forEachRemaining(key -> { + Object value = jsonObject.get(key); + handleValue(key, value); + }); + } + + public void handleJSONArray(String key, JSONArray jsonArray) { + Iterator jsonArrayIterator = jsonArray.iterator(); + jsonArrayIterator.forEachRemaining(element -> { + handleValue(key, element); + }); + } + + public Map getKeyValuePairs() { + return keyValuePairs; + } + + public void setKeyValuePairs(Map keyValuePairs) { + this.keyValuePairs = keyValuePairs; + } + +} diff --git a/json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java b/json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java new file mode 100644 index 0000000000..55cfdab53b --- /dev/null +++ b/json/src/test/java/com/baeldung/jsonobject/iterate/JSONObjectIteratorUnitTest.java @@ -0,0 +1,79 @@ +package com.baeldung.jsonobject.iterate; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Map; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; + +public class JSONObjectIteratorUnitTest { + + private JSONObjectIterator jsonObjectIterator = new JSONObjectIterator(); + + @Test + public void givenJSONObject_whenIterating_thenGetKeyValuePairs() { + JSONObject jsonObject = getJsonObject(); + + jsonObjectIterator.handleJSONObject(jsonObject); + + Map keyValuePairs = jsonObjectIterator.getKeyValuePairs(); + assertThat(keyValuePairs.get("rType")).isEqualTo("Regular"); + assertThat(keyValuePairs.get("rId")).isEqualTo("1001"); + assertThat(keyValuePairs.get("cType")).isEqualTo("Chocolate"); + assertThat(keyValuePairs.get("cId")).isEqualTo("1002"); + assertThat(keyValuePairs.get("bType")).isEqualTo("BlueBerry"); + assertThat(keyValuePairs.get("bId")).isEqualTo("1003"); + assertThat(keyValuePairs.get("name")).isEqualTo("Cake"); + assertThat(keyValuePairs.get("cakeId")).isEqualTo("0001"); + assertThat(keyValuePairs.get("type")).isEqualTo("donut"); + assertThat(keyValuePairs.get("Type")).isEqualTo("Maple"); + assertThat(keyValuePairs.get("tId")).isEqualTo("5001"); + assertThat(keyValuePairs.get("batters") + .toString()).isEqualTo("[{\"rType\":\"Regular\",\"rId\":\"1001\"},{\"cType\":\"Chocolate\",\"cId\":\"1002\"},{\"bType\":\"BlueBerry\",\"bId\":\"1003\"}]"); + assertThat(keyValuePairs.get("cakeShapes") + .toString()).isEqualTo("[\"square\",\"circle\",\"heart\"]"); + assertThat(keyValuePairs.get("topping") + .toString()).isEqualTo("{\"Type\":\"Maple\",\"tId\":\"5001\"}"); + } + + private JSONObject getJsonObject() { + JSONObject cake = new JSONObject(); + cake.put("cakeId", "0001"); + cake.put("type", "donut"); + cake.put("name", "Cake"); + + JSONArray batters = new JSONArray(); + JSONObject regular = new JSONObject(); + regular.put("rId", "1001"); + regular.put("rType", "Regular"); + batters.put(regular); + JSONObject chocolate = new JSONObject(); + chocolate.put("cId", "1002"); + chocolate.put("cType", "Chocolate"); + batters.put(chocolate); + JSONObject blueberry = new JSONObject(); + blueberry.put("bId", "1003"); + blueberry.put("bType", "BlueBerry"); + batters.put(blueberry); + + JSONArray cakeShapes = new JSONArray(); + cakeShapes.put("square"); + cakeShapes.put("circle"); + cakeShapes.put("heart"); + + cake.put("cakeShapes", cakeShapes); + + cake.put("batters", batters); + + JSONObject topping = new JSONObject(); + topping.put("tId", "5001"); + topping.put("Type", "Maple"); + + cake.put("topping", topping); + + return cake; + } + +} From 5960b3585cd128d058e2c46982dbccabaebbed78 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 22 Feb 2019 21:47:23 +0000 Subject: [PATCH 085/496] Add new authority name --- .../main/java/com/baeldung/security/AuthoritiesConstants.java | 2 ++ .../src/main/resources/config/liquibase/authorities.csv | 1 + 2 files changed, 3 insertions(+) diff --git a/jhipster/jhipster-monolithic/src/main/java/com/baeldung/security/AuthoritiesConstants.java b/jhipster/jhipster-monolithic/src/main/java/com/baeldung/security/AuthoritiesConstants.java index 40cf54e4f6..a28edd97de 100644 --- a/jhipster/jhipster-monolithic/src/main/java/com/baeldung/security/AuthoritiesConstants.java +++ b/jhipster/jhipster-monolithic/src/main/java/com/baeldung/security/AuthoritiesConstants.java @@ -7,6 +7,8 @@ public final class AuthoritiesConstants { public static final String ADMIN = "ROLE_ADMIN"; + public static final String MANAGER = "ROLE_MANAGER"; + public static final String USER = "ROLE_USER"; public static final String ANONYMOUS = "ROLE_ANONYMOUS"; diff --git a/jhipster/jhipster-monolithic/src/main/resources/config/liquibase/authorities.csv b/jhipster/jhipster-monolithic/src/main/resources/config/liquibase/authorities.csv index af5c6dfa18..91f05d6303 100644 --- a/jhipster/jhipster-monolithic/src/main/resources/config/liquibase/authorities.csv +++ b/jhipster/jhipster-monolithic/src/main/resources/config/liquibase/authorities.csv @@ -1,3 +1,4 @@ name ROLE_ADMIN +ROLE_MANAGER ROLE_USER From 9a7e0ed790ac8bd02fbbab3da7f65ac58745c77a Mon Sep 17 00:00:00 2001 From: soufiane-cheouati <46105138+soufiane-cheouati@users.noreply.github.com> Date: Sat, 23 Feb 2019 05:14:09 +0000 Subject: [PATCH 086/496] Adding Reflections files (#6393) * Adding Reflections dependency * Adding Reflections java class * Adding Reflections UT --- libraries/pom.xml | 1813 +++++++++-------- .../baeldung/reflections/ReflectionsApp.java | 71 + .../reflections/ReflectionsUnitTest.java | 50 + 3 files changed, 1032 insertions(+), 902 deletions(-) create mode 100644 libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java create mode 100644 libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java diff --git a/libraries/pom.xml b/libraries/pom.xml index d067525315..602f3a991e 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -1,902 +1,911 @@ - - - 4.0.0 - libraries - libraries - - - parent-modules - com.baeldung - 1.0.0-SNAPSHOT - - - - - - com.typesafe.akka - akka-actor_2.12 - ${typesafe-akka.version} - - - - com.typesafe.akka - akka-testkit_2.12 - ${typesafe-akka.version} - test - - - - - org.asynchttpclient - async-http-client - ${async.http.client.version} - - - - org.beykery - neuroph - ${neuroph.version} - - - - cglib - cglib - ${cglib.version} - - - - com.opencsv - opencsv - ${opencsv.version} - - - org.apache.commons - commons-lang3 - ${commons-lang.version} - - - commons-net - commons-net - ${commons-net.version} - - - tec.units - unit-ri - ${unit-ri.version} - - - org.jasypt - jasypt - ${jasypt.version} - - - org.javatuples - javatuples - ${javatuples.version} - - - org.javassist - javassist - ${javaassist.version} - - - - org.assertj - assertj-core - ${assertj.version} - - - org.skyscreamer - jsonassert - ${jsonassert.version} - - - org.javers - javers-core - ${javers.version} - - - - io.nats - jnats - ${jnats.version} - - - - rome - rome - ${rome.version} - - - io.specto - hoverfly-java - ${hoverfly-java.version} - - - org.apache.httpcomponents - httpclient - ${httpclient.version} - - - commons-logging - commons-logging - - - - - net.serenity-bdd - serenity-core - ${serenity.version} - test - - - org.asciidoctor - asciidoctorj - - - - - net.serenity-bdd - serenity-junit - ${serenity.version} - test - - - net.serenity-bdd - serenity-jbehave - ${serenity.jbehave.version} - test - - - net.serenity-bdd - serenity-rest-assured - ${serenity.version} - test - - - net.serenity-bdd - serenity-jira-requirements-provider - ${serenity.jira.version} - test - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - - - org.datanucleus - javax.jdo - ${javax.jdo.version} - - - org.datanucleus - datanucleus-core - ${datanucleus.version} - - - org.datanucleus - datanucleus-api-jdo - ${datanucleus.version} - - - org.datanucleus - datanucleus-rdbms - ${datanucleus.version} - - - org.datanucleus - datanucleus-maven-plugin - ${datanucleus-maven-plugin.version} - - - org.datanucleus - datanucleus-xml - ${datanucleus-xml.version} - - - org.datanucleus - datanucleus-jdo-query - ${datanucleus-jdo-query.version} - - - net.openhft - chronicle - ${chronicle.version} - - - com.sun.java - tools - - - - - org.springframework - spring-web - ${spring.version} - - - net.serenity-bdd - serenity-spring - ${serenity.version} - test - - - net.serenity-bdd - serenity-screenplay - ${serenity.version} - test - - - net.serenity-bdd - serenity-screenplay-webdriver - ${serenity.version} - test - - - - - org.lucee - jets3t - ${jets3t-version} - - - org.lucee - commons-codec - ${commons-codec-version} - - - - io.rest-assured - spring-mock-mvc - ${spring-mock-mvc.version} - test - - - org.multiverse - multiverse-core - ${multiverse.version} - - - com.zaxxer - HikariCP - ${HikariCP.version} - compile - - - com.h2database - h2 - ${h2.version} - - - pl.pragmatists - JUnitParams - ${jUnitParams.version} - test - - - org.quartz-scheduler - quartz - ${quartz.version} - - - one.util - streamex - ${streamex.version} - - - org.jooq - jool - ${jool.version} - - - org.openjdk.jmh - jmh-core - ${jmh.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh.version} - - - junit - junit - ${junit.version} - test - - - info.debatty - java-lsh - ${java-lsh.version} - - - au.com.dius - pact-jvm-consumer-junit_2.11 - ${pact.version} - test - - - org.codehaus.groovy - groovy-all - pom - ${groovy.version} - - - org.awaitility - awaitility - ${awaitility.version} - test - - - org.awaitility - awaitility-proxy - ${awaitility.version} - test - - - org.hamcrest - java-hamcrest - ${org.hamcrest.java-hamcrest.version} - test - - - net.agkn - hll - ${hll.version} - - - net.bytebuddy - byte-buddy - ${bytebuddy.version} - - - net.bytebuddy - byte-buddy-agent - ${bytebuddy.version} - - - org.pcollections - pcollections - ${pcollections.version} - - - com.machinezoo.noexception - noexception - ${noexception.version} - - - org.eclipse.collections - eclipse-collections - ${eclipse-collections.version} - - - io.vavr - vavr - ${vavr.version} - - - - - com.squareup.retrofit2 - retrofit - ${retrofit.version} - - - com.squareup.retrofit2 - converter-gson - ${retrofit.version} - - - com.squareup.retrofit2 - adapter-rxjava - ${retrofit.version} - - - com.squareup.okhttp3 - logging-interceptor - ${logging-interceptor.version} - - - com.darwinsys - hirondelle-date4j - ${hirondelle-date4j.version} - - - com.haulmont.yarg - yarg - ${yarg.version} - - - net.engio - mbassador - ${mbassador.version} - - - org.jdeferred - jdeferred-core - ${jdeferred.version} - - - com.codepoetics - protonpack - ${protonpack.version} - - - org.functionaljava - functionaljava - ${functionaljava.version} - - - org.functionaljava - functionaljava-java8 - ${functionaljava.version} - - - org.functionaljava - functionaljava-quickcheck - ${functionaljava.version} - - - org.functionaljava - functionaljava-java-core - ${functionaljava.version} - - - javax.cache - cache-api - ${cache.version} - - - com.hazelcast - hazelcast - ${hazelcast.version} - - - org.jgrapht - jgrapht-core - ${jgrapht.version} - - - com.netopyr.wurmloch - wurmloch-crdt - ${crdt.version} - - - org.docx4j - docx4j - ${docx4j.version} - - - javax.xml.bind - jaxb-api - ${jaxb-api.version} - - - com.github.ben-manes.caffeine - caffeine - ${caffeine.version} - - - org.bouncycastle - bcprov-jdk15on - ${bouncycastle.version} - - - org.bouncycastle - bcpkix-jdk15on - ${bouncycastle.version} - - - com.google.http-client - google-http-client - ${googleclient.version} - - - com.google.http-client - google-http-client-jackson2 - ${googleclient.version} - - - com.google.http-client - google-http-client-gson - ${googleclient.version} - - - org.infinispan - infinispan-core - ${infinispan.version} - - - - - com.github.docker-java - docker-java - ${docker.version} - - - org.slf4j - slf4j-log4j12 - - - org.slf4j - jcl-over-slf4j - - - ch.qos.logback - logback-classic - - - - - com.sun.jersey - jersey-client - ${jersey.version} - - - - - - com.google.api-client - google-api-client - ${google-api.version} - - - com.google.oauth-client - google-oauth-client-jetty - ${google-api.version} - - - com.google.apis - google-api-services-sheets - ${google-sheets.version} - - - org.apache.kafka - kafka-streams - ${kafka.version} - - - org.apache.kafka - kafka-clients - ${kafka.version} - - - org.slf4j - slf4j-log4j12 - - - - - org.apache.kafka - kafka-clients - ${kafka.version} - test - test - - - - org.milyn - milyn-smooks-all - ${smooks.version} - - - com.mashape.unirest - unirest-java - ${unirest.version} - - - - - io.javalin - javalin - ${javalin.version} - - - - io.atlassian.fugue - fugue - ${fugue.version} - - - - org.jctools - jctools-core - ${jctools.version} - - - - - io.github.resilience4j - resilience4j-circuitbreaker - ${resilience4j.version} - - - io.github.resilience4j - resilience4j-ratelimiter - ${resilience4j.version} - - - io.github.resilience4j - resilience4j-bulkhead - ${resilience4j.version} - - - io.github.resilience4j - resilience4j-retry - ${resilience4j.version} - - - io.github.resilience4j - resilience4j-cache - ${resilience4j.version} - - - io.github.resilience4j - resilience4j-timelimiter - ${resilience4j.version} - - - com.squareup - javapoet - ${javapoet.version} - - - org.hamcrest - hamcrest-all - ${hamcrest-all.version} - test - - - - org.yaml - snakeyaml - ${snakeyaml.version} - - - - com.numericalmethod - suanshu - ${suanshu.version} - - - - org.derive4j - derive4j - ${derive4j.version} - true - - - org.mockftpserver - MockFtpServer - ${mockftpserver.version} - test - - - - - - - - false - - bintray-cuba-platform-main - bintray - http://dl.bintray.com/cuba-platform/main - - - Apache Staging - https://repository.apache.org/content/groups/staging - - - nm-repo - Numerical Method's Maven Repository - http://repo.numericalmethod.com/maven/ - default - - - - - - - - maven-failsafe-plugin - ${maven-failsafe-plugin.version} - - - chromedriver - - - - - net.serenity-bdd.maven.plugins - serenity-maven-plugin - ${serenity.plugin.version} - - - serenity-reports - post-integration-test - - aggregate - - - - - - - org.datanucleus - datanucleus-maven-plugin - ${datanucleus-maven-plugin.version} - - JDO - ${basedir}/datanucleus.properties - ${basedir}/log4j.properties - true - false - - - - - process-classes - - enhance - - - - - - - org.apache.maven.plugins - maven-jar-plugin - ${maven-jar-plugin.version} - - - **/log4j.properties - - - - com.baeldung.neuroph.NeurophXOR - - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 2.2 - - - package - - shade - - - benchmarks - - - org.openjdk.jmh.Main - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - - - 4.0.0 - 1.21 - 1.23.0 - 0.1.0 - 0.7.0 - 3.2.7 - 3.6 - 1.9.2 - 1.2 - 3.21.0-GA - 3.6.2 - 1.5.0 - 3.1.0 - 4.5.3 - 1.4.196 - 1.0 - - 4.5.3 - 2.9.7 - 2.92 - 1.9.26 - 1.41.0 - 1.9.0 - 1.9.27 - 1.1.0 - 4.12 - 0.10 - 3.5.0 - 3.0.0 - 2.0.0.0 - 1.6.0 - 1.7.1 - 2.1.2 - 1.0 - 8.2.0 - 0.6.5 - 0.9.0 - 15.2 - 1.5.1 - 2.3.0 - 2.10 - 1.5.1 - 1.15 - 1.0.3 - 1.0.0 - 3.10.2 - 2.5.5 - 1.23.0 - v4-rev493-1.21.0 - 2.0.0 - 1.7.0 - 3.0.14 - 2.2.0 - 9.1.5.Final - 4.1 - 1.4.9 - 2.1.2 - 1.10.L001 - 0.9.4.0006L - 2.1.2 - 2.5.11 - 0.12.1 - 1.10.0 - 1.3 - 0.8.1 - 3.2.0-m7 - 5.1.1 - 5.0.2 - 5.0.0-release - 5.0.2 - 3.6.4 - 4.3.8.RELEASE - 3.0.3 - 2.6.3 - 2.3.0 - 0.9.12 - 1.19 - 2.5.2 - 1.1.0 - 3.9.0 - 2.0.4 - 1.3.1 - 1.2.6 - 4.8.1 - 1.0.1 - 3.3.5 - 2.1 - 1.58 - 1.19.4 - 1.6.0 - 4.5.1 - 3.3.0 - 3.0.2 - 1.1.0 - 2.7.1 - 3.6 - - - + + + 4.0.0 + libraries + libraries + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + + + + + com.typesafe.akka + akka-actor_2.12 + ${typesafe-akka.version} + + + + com.typesafe.akka + akka-testkit_2.12 + ${typesafe-akka.version} + test + + + + + org.asynchttpclient + async-http-client + ${async.http.client.version} + + + + org.beykery + neuroph + ${neuroph.version} + + + + cglib + cglib + ${cglib.version} + + + + com.opencsv + opencsv + ${opencsv.version} + + + org.apache.commons + commons-lang3 + ${commons-lang.version} + + + commons-net + commons-net + ${commons-net.version} + + + tec.units + unit-ri + ${unit-ri.version} + + + org.jasypt + jasypt + ${jasypt.version} + + + org.javatuples + javatuples + ${javatuples.version} + + + org.javassist + javassist + ${javaassist.version} + + + + org.assertj + assertj-core + ${assertj.version} + + + org.skyscreamer + jsonassert + ${jsonassert.version} + + + org.javers + javers-core + ${javers.version} + + + + io.nats + jnats + ${jnats.version} + + + + rome + rome + ${rome.version} + + + io.specto + hoverfly-java + ${hoverfly-java.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + commons-logging + commons-logging + + + + + net.serenity-bdd + serenity-core + ${serenity.version} + test + + + org.asciidoctor + asciidoctorj + + + + + net.serenity-bdd + serenity-junit + ${serenity.version} + test + + + net.serenity-bdd + serenity-jbehave + ${serenity.jbehave.version} + test + + + net.serenity-bdd + serenity-rest-assured + ${serenity.version} + test + + + net.serenity-bdd + serenity-jira-requirements-provider + ${serenity.jira.version} + test + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + + org.datanucleus + javax.jdo + ${javax.jdo.version} + + + org.datanucleus + datanucleus-core + ${datanucleus.version} + + + org.datanucleus + datanucleus-api-jdo + ${datanucleus.version} + + + org.datanucleus + datanucleus-rdbms + ${datanucleus.version} + + + org.datanucleus + datanucleus-maven-plugin + ${datanucleus-maven-plugin.version} + + + org.datanucleus + datanucleus-xml + ${datanucleus-xml.version} + + + org.datanucleus + datanucleus-jdo-query + ${datanucleus-jdo-query.version} + + + net.openhft + chronicle + ${chronicle.version} + + + com.sun.java + tools + + + + + org.springframework + spring-web + ${spring.version} + + + net.serenity-bdd + serenity-spring + ${serenity.version} + test + + + net.serenity-bdd + serenity-screenplay + ${serenity.version} + test + + + net.serenity-bdd + serenity-screenplay-webdriver + ${serenity.version} + test + + + + + org.lucee + jets3t + ${jets3t-version} + + + org.lucee + commons-codec + ${commons-codec-version} + + + + io.rest-assured + spring-mock-mvc + ${spring-mock-mvc.version} + test + + + org.multiverse + multiverse-core + ${multiverse.version} + + + com.zaxxer + HikariCP + ${HikariCP.version} + compile + + + com.h2database + h2 + ${h2.version} + + + pl.pragmatists + JUnitParams + ${jUnitParams.version} + test + + + org.quartz-scheduler + quartz + ${quartz.version} + + + one.util + streamex + ${streamex.version} + + + org.jooq + jool + ${jool.version} + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + junit + junit + ${junit.version} + test + + + info.debatty + java-lsh + ${java-lsh.version} + + + au.com.dius + pact-jvm-consumer-junit_2.11 + ${pact.version} + test + + + org.codehaus.groovy + groovy-all + pom + ${groovy.version} + + + org.awaitility + awaitility + ${awaitility.version} + test + + + org.awaitility + awaitility-proxy + ${awaitility.version} + test + + + org.hamcrest + java-hamcrest + ${org.hamcrest.java-hamcrest.version} + test + + + net.agkn + hll + ${hll.version} + + + net.bytebuddy + byte-buddy + ${bytebuddy.version} + + + net.bytebuddy + byte-buddy-agent + ${bytebuddy.version} + + + org.pcollections + pcollections + ${pcollections.version} + + + com.machinezoo.noexception + noexception + ${noexception.version} + + + org.eclipse.collections + eclipse-collections + ${eclipse-collections.version} + + + io.vavr + vavr + ${vavr.version} + + + + + com.squareup.retrofit2 + retrofit + ${retrofit.version} + + + com.squareup.retrofit2 + converter-gson + ${retrofit.version} + + + com.squareup.retrofit2 + adapter-rxjava + ${retrofit.version} + + + com.squareup.okhttp3 + logging-interceptor + ${logging-interceptor.version} + + + com.darwinsys + hirondelle-date4j + ${hirondelle-date4j.version} + + + com.haulmont.yarg + yarg + ${yarg.version} + + + net.engio + mbassador + ${mbassador.version} + + + org.jdeferred + jdeferred-core + ${jdeferred.version} + + + com.codepoetics + protonpack + ${protonpack.version} + + + org.functionaljava + functionaljava + ${functionaljava.version} + + + org.functionaljava + functionaljava-java8 + ${functionaljava.version} + + + org.functionaljava + functionaljava-quickcheck + ${functionaljava.version} + + + org.functionaljava + functionaljava-java-core + ${functionaljava.version} + + + javax.cache + cache-api + ${cache.version} + + + com.hazelcast + hazelcast + ${hazelcast.version} + + + org.jgrapht + jgrapht-core + ${jgrapht.version} + + + com.netopyr.wurmloch + wurmloch-crdt + ${crdt.version} + + + org.docx4j + docx4j + ${docx4j.version} + + + javax.xml.bind + jaxb-api + ${jaxb-api.version} + + + com.github.ben-manes.caffeine + caffeine + ${caffeine.version} + + + org.bouncycastle + bcprov-jdk15on + ${bouncycastle.version} + + + org.bouncycastle + bcpkix-jdk15on + ${bouncycastle.version} + + + com.google.http-client + google-http-client + ${googleclient.version} + + + com.google.http-client + google-http-client-jackson2 + ${googleclient.version} + + + com.google.http-client + google-http-client-gson + ${googleclient.version} + + + org.infinispan + infinispan-core + ${infinispan.version} + + + + + com.github.docker-java + docker-java + ${docker.version} + + + org.slf4j + slf4j-log4j12 + + + org.slf4j + jcl-over-slf4j + + + ch.qos.logback + logback-classic + + + + + com.sun.jersey + jersey-client + ${jersey.version} + + + + + + com.google.api-client + google-api-client + ${google-api.version} + + + com.google.oauth-client + google-oauth-client-jetty + ${google-api.version} + + + com.google.apis + google-api-services-sheets + ${google-sheets.version} + + + org.apache.kafka + kafka-streams + ${kafka.version} + + + org.apache.kafka + kafka-clients + ${kafka.version} + + + org.slf4j + slf4j-log4j12 + + + + + org.apache.kafka + kafka-clients + ${kafka.version} + test + test + + + + org.milyn + milyn-smooks-all + ${smooks.version} + + + com.mashape.unirest + unirest-java + ${unirest.version} + + + + + io.javalin + javalin + ${javalin.version} + + + + io.atlassian.fugue + fugue + ${fugue.version} + + + + org.jctools + jctools-core + ${jctools.version} + + + + + io.github.resilience4j + resilience4j-circuitbreaker + ${resilience4j.version} + + + io.github.resilience4j + resilience4j-ratelimiter + ${resilience4j.version} + + + io.github.resilience4j + resilience4j-bulkhead + ${resilience4j.version} + + + io.github.resilience4j + resilience4j-retry + ${resilience4j.version} + + + io.github.resilience4j + resilience4j-cache + ${resilience4j.version} + + + io.github.resilience4j + resilience4j-timelimiter + ${resilience4j.version} + + + com.squareup + javapoet + ${javapoet.version} + + + org.hamcrest + hamcrest-all + ${hamcrest-all.version} + test + + + + org.yaml + snakeyaml + ${snakeyaml.version} + + + + com.numericalmethod + suanshu + ${suanshu.version} + + + + org.derive4j + derive4j + ${derive4j.version} + true + + + org.mockftpserver + MockFtpServer + ${mockftpserver.version} + test + + + + + org.reflections + reflections + ${reflections.version} + + + + + + + + + false + + bintray-cuba-platform-main + bintray + http://dl.bintray.com/cuba-platform/main + + + Apache Staging + https://repository.apache.org/content/groups/staging + + + nm-repo + Numerical Method's Maven Repository + http://repo.numericalmethod.com/maven/ + default + + + + + + + + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + + chromedriver + + + + + net.serenity-bdd.maven.plugins + serenity-maven-plugin + ${serenity.plugin.version} + + + serenity-reports + post-integration-test + + aggregate + + + + + + + org.datanucleus + datanucleus-maven-plugin + ${datanucleus-maven-plugin.version} + + JDO + ${basedir}/datanucleus.properties + ${basedir}/log4j.properties + true + false + + + + + process-classes + + enhance + + + + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + **/log4j.properties + + + + com.baeldung.neuroph.NeurophXOR + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.2 + + + package + + shade + + + benchmarks + + + org.openjdk.jmh.Main + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + + 4.0.0 + 1.21 + 1.23.0 + 0.1.0 + 0.7.0 + 3.2.7 + 3.6 + 1.9.2 + 1.2 + 3.21.0-GA + 3.6.2 + 1.5.0 + 3.1.0 + 4.5.3 + 1.4.196 + 1.0 + + 4.5.3 + 2.9.7 + 2.92 + 1.9.26 + 1.41.0 + 1.9.0 + 1.9.27 + 1.1.0 + 4.12 + 0.10 + 3.5.0 + 3.0.0 + 2.0.0.0 + 1.6.0 + 1.7.1 + 2.1.2 + 1.0 + 8.2.0 + 0.6.5 + 0.9.0 + 15.2 + 1.5.1 + 2.3.0 + 2.10 + 1.5.1 + 1.15 + 1.0.3 + 1.0.0 + 3.10.2 + 2.5.5 + 1.23.0 + v4-rev493-1.21.0 + 2.0.0 + 1.7.0 + 3.0.14 + 2.2.0 + 9.1.5.Final + 4.1 + 1.4.9 + 2.1.2 + 1.10.L001 + 0.9.4.0006L + 2.1.2 + 2.5.11 + 0.12.1 + 1.10.0 + 1.3 + 0.8.1 + 3.2.0-m7 + 5.1.1 + 5.0.2 + 5.0.0-release + 5.0.2 + 3.6.4 + 4.3.8.RELEASE + 3.0.3 + 2.6.3 + 2.3.0 + 0.9.12 + 1.19 + 2.5.2 + 1.1.0 + 3.9.0 + 2.0.4 + 1.3.1 + 1.2.6 + 4.8.1 + 1.0.1 + 3.3.5 + 2.1 + 1.58 + 1.19.4 + 1.6.0 + 4.5.1 + 3.3.0 + 3.0.2 + 1.1.0 + 2.7.1 + 3.6 + 0.9.11 + + + \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java b/libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java new file mode 100644 index 0000000000..30da8ea837 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/reflections/ReflectionsApp.java @@ -0,0 +1,71 @@ +package com.baeldung.reflections; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Date; +import java.util.Set; +import java.util.regex.Pattern; + +import org.reflections.Reflections; +import org.reflections.scanners.MethodAnnotationsScanner; +import org.reflections.scanners.MethodParameterScanner; +import org.reflections.scanners.ResourcesScanner; +import org.reflections.scanners.Scanner; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; + +public class ReflectionsApp { + + public Set> getReflectionsSubTypes() { + Reflections reflections = new Reflections("org.reflections"); + Set> scannersSet = reflections.getSubTypesOf(Scanner.class); + return scannersSet; + } + + public Set> getJDKFunctinalInterfaces() { + Reflections reflections = new Reflections("java.util.function"); + Set> typesSet = reflections.getTypesAnnotatedWith(FunctionalInterface.class); + return typesSet; + } + + public Set getDateDeprecatedMethods() { + Reflections reflections = new Reflections(java.util.Date.class, new MethodAnnotationsScanner()); + Set deprecatedMethodsSet = reflections.getMethodsAnnotatedWith(Deprecated.class); + return deprecatedMethodsSet; + } + + @SuppressWarnings("rawtypes") + public Set getDateDeprecatedConstructors() { + Reflections reflections = new Reflections(java.util.Date.class, new MethodAnnotationsScanner()); + Set constructorsSet = reflections.getConstructorsAnnotatedWith(Deprecated.class); + return constructorsSet; + } + + public Set getMethodsWithDateParam() { + Reflections reflections = new Reflections(java.text.SimpleDateFormat.class, new MethodParameterScanner()); + Set methodsSet = reflections.getMethodsMatchParams(Date.class); + return methodsSet; + } + + public Set getMethodsWithVoidReturn() { + Reflections reflections = new Reflections(java.text.SimpleDateFormat.class, new MethodParameterScanner()); + Set methodsSet = reflections.getMethodsReturn(void.class); + return methodsSet; + } + + public Set getPomXmlPaths() { + Reflections reflections = new Reflections(new ResourcesScanner()); + Set resourcesSet = reflections.getResources(Pattern.compile(".*pom\\.xml")); + return resourcesSet; + } + + public Set> getReflectionsSubTypesUsingBuilder() { + Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage("org.reflections")) + .setScanners(new SubTypesScanner())); + + Set> scannersSet = reflections.getSubTypesOf(Scanner.class); + return scannersSet; + } + +} diff --git a/libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java b/libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java new file mode 100644 index 0000000000..9a3ef0747b --- /dev/null +++ b/libraries/src/test/java/com/baeldung/reflections/ReflectionsUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.reflections; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +import org.junit.jupiter.api.Test; + +public class ReflectionsUnitTest { + + @Test + public void givenTypeThenGetAllSubTypes() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getReflectionsSubTypes() + .isEmpty()); + } + + @Test + public void givenTypeAndUsingBuilderThenGetAllSubTypes() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getReflectionsSubTypesUsingBuilder() + .isEmpty()); + } + + @Test + public void givenAnnotationThenGetAllAnnotatedMethods() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getDateDeprecatedMethods() + .isEmpty()); + } + + @Test + public void givenAnnotationThenGetAllAnnotatedConstructors() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getDateDeprecatedConstructors() + .isEmpty()); + } + + @Test + public void givenParamTypeThenGetAllMethods() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getMethodsWithDateParam() + .isEmpty()); + } + + @Test + public void givenReturnTypeThenGetAllMethods() { + ReflectionsApp reflectionsApp = new ReflectionsApp(); + assertFalse(reflectionsApp.getMethodsWithVoidReturn() + .isEmpty()); + } +} From 326bfbe712d9461f5495d48e12bf99f49795bd82 Mon Sep 17 00:00:00 2001 From: Wosin Date: Sat, 23 Feb 2019 07:20:28 +0100 Subject: [PATCH 087/496] Fixed error with missing getter for Derive4J (#6391) --- .../src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java b/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java index 9f53f3d25b..bee947df12 100644 --- a/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java +++ b/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java @@ -6,7 +6,7 @@ import org.derive4j.Make; @Data(value = @Derive( inClass = "{ClassName}Impl", - make = {Make.lazyConstructor, Make.constructors} + make = {Make.lazyConstructor, Make.constructors, Make.getters} )) public interface LazyRequest { interface Cases{ From ed427464adfca5f3687710f3a08162e9b00fd7a8 Mon Sep 17 00:00:00 2001 From: Seun Matt Date: Sat, 23 Feb 2019 08:37:05 +0100 Subject: [PATCH 088/496] added example code for BAEL-2487 (#6383) * added example code for BAEL-2366 * moved example code for BAEL-2366 * example code for BAEL-1961 * moved example code into integration test * updated the test assertions * refactor the spring boot persistence mongodb module * remove redundant example code * declared the spring boot persistence module in the root pom * fixed issue with non-imported file * added example code for BAEL-2418 * added example code for BAEL-2549 * added example code for BAEL-2487 * refactor the maven module * updated the example code * updated the example code * updated the pom files * updated the pom files for verifier plugin --- maven/.gitignore | 3 +- maven/custom-rule/pom.xml | 69 +++++++++++++++++ .../com/baeldung/enforcer/MyCustomRule.java | 43 +++++++++++ maven/maven-enforcer/pom.xml | 74 +++++++++++++++++++ maven/pom.xml | 8 +- 5 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 maven/custom-rule/pom.xml create mode 100644 maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java create mode 100644 maven/maven-enforcer/pom.xml diff --git a/maven/.gitignore b/maven/.gitignore index f843ae9109..bae0b0d7ce 100644 --- a/maven/.gitignore +++ b/maven/.gitignore @@ -1 +1,2 @@ -/output-resources \ No newline at end of file +/output-resources +/.idea/ diff --git a/maven/custom-rule/pom.xml b/maven/custom-rule/pom.xml new file mode 100644 index 0000000000..f76e0db11e --- /dev/null +++ b/maven/custom-rule/pom.xml @@ -0,0 +1,69 @@ + + + + maven + com.baeldung + 0.0.1-SNAPSHOT + + 4.0.0 + custom-rule + + + 3.0.0-M2 + 2.0.9 + + + + + + + org.apache.maven.enforcer + enforcer-api + ${api.version} + + + org.apache.maven + maven-project + ${maven.version} + + + org.apache.maven + maven-core + ${maven.version} + + + org.apache.maven + maven-artifact + ${maven.version} + + + org.apache.maven + maven-plugin-api + ${maven.version} + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-9 + + + + + + + maven-verifier-plugin + ${maven.verifier.version} + + ../input-resources/verifications.xml + false + + + + + + + + + \ No newline at end of file diff --git a/maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java b/maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java new file mode 100644 index 0000000000..9b72f40bf1 --- /dev/null +++ b/maven/custom-rule/src/main/java/com/baeldung/enforcer/MyCustomRule.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 PloyRef + * Created by Seun Matt + * on 19 - 2 - 2019 + */ + +package com.baeldung.enforcer; + +import org.apache.maven.enforcer.rule.api.EnforcerRule; +import org.apache.maven.enforcer.rule.api.EnforcerRuleException; +import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; + +public class MyCustomRule implements EnforcerRule { + + public void execute(EnforcerRuleHelper enforcerRuleHelper) throws EnforcerRuleException { + + try { + + String groupId = (String) enforcerRuleHelper.evaluate("${project.groupId}"); + + if (groupId == null || !groupId.startsWith("org.baeldung")) { + throw new EnforcerRuleException("Project group id does not start with org.baeldung"); + } + + } + catch (ExpressionEvaluationException ex ) { + throw new EnforcerRuleException( "Unable to lookup an expression " + ex.getLocalizedMessage(), ex ); + } + } + + public boolean isCacheable() { + return false; + } + + public boolean isResultValid(EnforcerRule enforcerRule) { + return false; + } + + public String getCacheId() { + return null; + } +} diff --git a/maven/maven-enforcer/pom.xml b/maven/maven-enforcer/pom.xml new file mode 100644 index 0000000000..d54471e66c --- /dev/null +++ b/maven/maven-enforcer/pom.xml @@ -0,0 +1,74 @@ + + + + maven + com.baeldung + 0.0.1-SNAPSHOT + + 4.0.0 + maven-enforcer + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M2 + + + + + + + + + + enforce + + enforce + + + + + + 3.0 + Invalid Maven version. It should, at least, be 3.0 + + + 1.8 + + + ui + WARN + + + cook + WARN + + + local,base + Missing active profiles + WARN + + + + + + + + + + maven-verifier-plugin + ${maven.verifier.version} + + ../input-resources/verifications.xml + false + + + + + + + \ No newline at end of file diff --git a/maven/pom.xml b/maven/pom.xml index 01fd28db74..942bf683e2 100644 --- a/maven/pom.xml +++ b/maven/pom.xml @@ -4,8 +4,12 @@ com.baeldung maven 0.0.1-SNAPSHOT - maven - war + + custom-rule + maven-enforcer + + maven + pom From c2a300baae2480bb69fd451fa4c321232c35285e Mon Sep 17 00:00:00 2001 From: dcalap Date: Sat, 23 Feb 2019 14:37:02 +0100 Subject: [PATCH 089/496] BAEL-2738 - Convert String to JsonObject with GSON (#6318) * BAEL-2738 - Convert String to JsonObject with GSON * BAEL-2738 Assertions added in example 2 (Using fromJson) * Update gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java Rename test name Co-Authored-By: dcalap * Update gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java Rename test Co-Authored-By: dcalap * Blank spaces added in order to separate given/when/then parts of the test --- .../JsonObjectConversionsUnitTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java diff --git a/gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java b/gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java new file mode 100644 index 0000000000..847ec1b85d --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/conversion/JsonObjectConversionsUnitTest.java @@ -0,0 +1,33 @@ +package org.baeldung.gson.conversion; + +import com.google.gson.*; +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +public class JsonObjectConversionsUnitTest { + + @Test + void whenUsingJsonParser_thenConvertToJsonObject() throws Exception { + // Example 1: Using JsonParser + String json = "{ \"name\": \"Baeldung\", \"java\": true }"; + + JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject(); + + Assert.assertTrue(jsonObject.isJsonObject()); + Assert.assertTrue(jsonObject.get("name").getAsString().equals("Baeldung")); + Assert.assertTrue(jsonObject.get("java").getAsBoolean() == true); + } + + @Test + void whenUsingGsonInstanceFromJson_thenConvertToJsonObject() throws Exception { + // Example 2: Using fromJson + String json = "{ \"name\": \"Baeldung\", \"java\": true }"; + + JsonObject convertedObject = new Gson().fromJson(json, JsonObject.class); + + Assert.assertTrue(convertedObject.isJsonObject()); + Assert.assertTrue(convertedObject.get("name").getAsString().equals("Baeldung")); + Assert.assertTrue(convertedObject.get("java").getAsBoolean() == true); + } + +} From a0a02bb31418e8572b6929fa844497a2bee88cf6 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sat, 23 Feb 2019 20:07:29 +0530 Subject: [PATCH 090/496] [BAEL-12669] - Reverted guest module changes --- guest/remote-debugging/pom.xml | 8 ++++---- guest/slf4j/guide/pom.xml | 7 +++---- guest/spring-boot-app/pom.xml | 7 +++---- guest/spring-mvc/pom.xml | 8 ++++---- guest/spring-security/pom.xml | 8 ++++---- guest/webservices/spring-rest-service/pom.xml | 7 +++---- 6 files changed, 21 insertions(+), 24 deletions(-) diff --git a/guest/remote-debugging/pom.xml b/guest/remote-debugging/pom.xml index 5c6a2b3165..137e00b719 100644 --- a/guest/remote-debugging/pom.xml +++ b/guest/remote-debugging/pom.xml @@ -9,10 +9,10 @@ war - parent-boot-1 - com.baeldung - 0.0.1-SNAPSHOT - ../../parent-boot-1 + org.springframework.boot + spring-boot-starter-parent + 1.5.8.RELEASE + diff --git a/guest/slf4j/guide/pom.xml b/guest/slf4j/guide/pom.xml index b69efee32a..29aa54b426 100644 --- a/guest/slf4j/guide/pom.xml +++ b/guest/slf4j/guide/pom.xml @@ -9,10 +9,9 @@ pom - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../../../parent-boot-2 + org.springframework.boot + spring-boot-starter-parent + 2.0.6.RELEASE diff --git a/guest/spring-boot-app/pom.xml b/guest/spring-boot-app/pom.xml index ab3181b676..0f0c37cb7c 100644 --- a/guest/spring-boot-app/pom.xml +++ b/guest/spring-boot-app/pom.xml @@ -8,10 +8,9 @@ war - parent-boot-1 - com.baeldung - 0.0.1-SNAPSHOT - ../../parent-boot-1 + org.springframework.boot + spring-boot-starter-parent + 1.5.3.RELEASE diff --git a/guest/spring-mvc/pom.xml b/guest/spring-mvc/pom.xml index b9d0899c77..991fa59d58 100644 --- a/guest/spring-mvc/pom.xml +++ b/guest/spring-mvc/pom.xml @@ -10,10 +10,10 @@ Spring MVC sample project - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../../parent-boot-2 + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + diff --git a/guest/spring-security/pom.xml b/guest/spring-security/pom.xml index d38be54114..a184693127 100644 --- a/guest/spring-security/pom.xml +++ b/guest/spring-security/pom.xml @@ -9,10 +9,10 @@ Spring Security Sample Project - parent-boot-2 - com.baeldung - 0.0.1-SNAPSHOT - ../../parent-boot-2 + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + diff --git a/guest/webservices/spring-rest-service/pom.xml b/guest/webservices/spring-rest-service/pom.xml index 8849b82a3e..c86fdfd829 100644 --- a/guest/webservices/spring-rest-service/pom.xml +++ b/guest/webservices/spring-rest-service/pom.xml @@ -8,10 +8,9 @@ war - parent-boot-1 - com.baeldung - 0.0.1-SNAPSHOT - ../../../parent-boot-1 + org.springframework.boot + spring-boot-starter-parent + 1.5.4.RELEASE From c8e94b927d2436e40c761afc9a73437e8627e817 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sat, 23 Feb 2019 20:10:59 +0530 Subject: [PATCH 091/496] [BAEL-12669] - Reverted guest module changes part 2 --- guest/remote-debugging/pom.xml | 1 - guest/slf4j/guide/pom.xml | 1 - guest/spring-boot-app/pom.xml | 1 - guest/spring-mvc/pom.xml | 1 - guest/spring-security/pom.xml | 1 - guest/webservices/spring-rest-service/pom.xml | 1 - 6 files changed, 6 deletions(-) diff --git a/guest/remote-debugging/pom.xml b/guest/remote-debugging/pom.xml index 137e00b719..07b9cc49d8 100644 --- a/guest/remote-debugging/pom.xml +++ b/guest/remote-debugging/pom.xml @@ -39,7 +39,6 @@ UTF-8 UTF-8 - 1.5.8.RELEASE diff --git a/guest/slf4j/guide/pom.xml b/guest/slf4j/guide/pom.xml index 29aa54b426..657ede73b6 100644 --- a/guest/slf4j/guide/pom.xml +++ b/guest/slf4j/guide/pom.xml @@ -59,6 +59,5 @@ UTF-8 1.8 2.0.0-beta.5 - 2.0.6.RELEASE diff --git a/guest/spring-boot-app/pom.xml b/guest/spring-boot-app/pom.xml index 0f0c37cb7c..423dadbb99 100644 --- a/guest/spring-boot-app/pom.xml +++ b/guest/spring-boot-app/pom.xml @@ -70,7 +70,6 @@ 8.0.43 UTF-8 1.8 - 1.5.3.RELEASE diff --git a/guest/spring-mvc/pom.xml b/guest/spring-mvc/pom.xml index 991fa59d58..3bffb1530d 100644 --- a/guest/spring-mvc/pom.xml +++ b/guest/spring-mvc/pom.xml @@ -30,7 +30,6 @@ UTF-8 UTF-8 - 2.0.0.RELEASE diff --git a/guest/spring-security/pom.xml b/guest/spring-security/pom.xml index a184693127..8be42ba32b 100644 --- a/guest/spring-security/pom.xml +++ b/guest/spring-security/pom.xml @@ -48,7 +48,6 @@ UTF-8 UTF-8 3.0.8.RELEASE - 2.0.0.RELEASE \ No newline at end of file diff --git a/guest/webservices/spring-rest-service/pom.xml b/guest/webservices/spring-rest-service/pom.xml index c86fdfd829..fcec8a3e12 100644 --- a/guest/webservices/spring-rest-service/pom.xml +++ b/guest/webservices/spring-rest-service/pom.xml @@ -49,7 +49,6 @@ 1.8 2.7.0 2.7.0 - 1.5.4.RELEASE \ No newline at end of file From b9b6115c78af5fa06decb5685367e7b39c91f49e Mon Sep 17 00:00:00 2001 From: Sushant Date: Sat, 23 Feb 2019 21:16:09 +0530 Subject: [PATCH 092/496] Moved to core-kotlin2 --- .../src/test/kotlin}/stringcomparison/StringComparisonTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {core-kotlin/src/test/kotlin/com/baeldung => core-kotlin-2/src/test/kotlin}/stringcomparison/StringComparisonTest.kt (97%) diff --git a/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt b/core-kotlin-2/src/test/kotlin/stringcomparison/StringComparisonTest.kt similarity index 97% rename from core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt rename to core-kotlin-2/src/test/kotlin/stringcomparison/StringComparisonTest.kt index 9528f62df5..45a8dd7e04 100644 --- a/core-kotlin/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt +++ b/core-kotlin-2/src/test/kotlin/stringcomparison/StringComparisonTest.kt @@ -1,4 +1,4 @@ -package com.baeldung.stringcomparison +package stringcomparison import org.junit.Test import kotlin.test.assertFalse From 59cfbaf5c41883e9e28997c464bfd07160c6d717 Mon Sep 17 00:00:00 2001 From: Doha2012 Date: Sat, 23 Feb 2019 22:15:52 +0200 Subject: [PATCH 093/496] add user-info endpoint live test (#6379) --- .../org/baeldung/config/AuthServerConfig.java | 2 +- .../org/baeldung/config/SecurityConfig.java | 3 +- .../baeldung/UserInfoEndpointLiveTest.java | 51 +++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 spring-security-sso/spring-security-sso-auth-server/src/test/java/org/baeldung/UserInfoEndpointLiveTest.java diff --git a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java index 07057c3875..0835f3d721 100644 --- a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java +++ b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/AuthServerConfig.java @@ -30,7 +30,7 @@ public class AuthServerConfig extends AuthorizationServerConfigurerAdapter { .authorizedGrantTypes("authorization_code") .scopes("user_info") .autoApprove(true) - .redirectUris("http://localhost:8082/ui/login","http://localhost:8083/ui2/login","http://localhost:8082/login") + .redirectUris("http://localhost:8082/ui/login","http://localhost:8083/ui2/login","http://localhost:8082/login","http://www.example.com/") // .accessTokenValiditySeconds(3600) ; // 1 hour } diff --git a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java index 5cebf4f4d2..2254de8e39 100644 --- a/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java +++ b/spring-security-sso/spring-security-sso-auth-server/src/main/java/org/baeldung/config/SecurityConfig.java @@ -22,7 +22,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { .authenticated() .and() .formLogin() - .permitAll(); + .permitAll() + .and().csrf().disable(); } // @formatter:on @Override diff --git a/spring-security-sso/spring-security-sso-auth-server/src/test/java/org/baeldung/UserInfoEndpointLiveTest.java b/spring-security-sso/spring-security-sso-auth-server/src/test/java/org/baeldung/UserInfoEndpointLiveTest.java new file mode 100644 index 0000000000..ffdb1df8fe --- /dev/null +++ b/spring-security-sso/spring-security-sso-auth-server/src/test/java/org/baeldung/UserInfoEndpointLiveTest.java @@ -0,0 +1,51 @@ +package org.baeldung; +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Test; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; + +import io.restassured.RestAssured; +import io.restassured.response.Response; + +public class UserInfoEndpointLiveTest { + + @Test + public void givenAccessToken_whenAccessUserInfoEndpoint_thenSuccess() { + String accessToken = obtainAccessTokenUsingAuthorizationCodeFlow("john","123"); + Response response = RestAssured.given().header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken).get("http://localhost:8081/auth/user/me"); + + assertEquals(HttpStatus.OK.value(), response.getStatusCode()); + assertEquals("john", response.jsonPath().get("name")); + } + + private String obtainAccessTokenUsingAuthorizationCodeFlow(String username, String password) { + final String authServerUri = "http://localhost:8081/auth"; + final String redirectUrl = "http://www.example.com/"; + final String authorizeUrl = authServerUri + "/oauth/authorize?response_type=code&client_id=SampleClientId&redirect_uri=" + redirectUrl; + final String tokenUrl = authServerUri + "/oauth/token"; + + // user login + Response response = RestAssured.given().formParams("username", username, "password", password).post(authServerUri + "/login"); + final String cookieValue = response.getCookie("JSESSIONID"); + + // get authorization code + RestAssured.given().cookie("JSESSIONID", cookieValue).get(authorizeUrl); + response = RestAssured.given().cookie("JSESSIONID", cookieValue).post(authorizeUrl); + assertEquals(HttpStatus.FOUND.value(), response.getStatusCode()); + final String location = response.getHeader(HttpHeaders.LOCATION); + final String code = location.substring(location.indexOf("code=") + 5); + + // get access token + Map params = new HashMap(); + params.put("grant_type", "authorization_code"); + params.put("code", code); + params.put("client_id", "SampleClientId"); + params.put("redirect_uri", redirectUrl); + response = RestAssured.given().auth().basic("SampleClientId", "secret").formParams(params).post(tokenUrl); + return response.jsonPath().getString("access_token"); + } +} From 6a36c90be5f8cde0e93f4bd44ed8840e21797e37 Mon Sep 17 00:00:00 2001 From: Joel Juarez Date: Sat, 23 Feb 2019 22:07:49 +0100 Subject: [PATCH 094/496] removed content type set in servlets --- .../src/main/java/com/baeldung/servlets/CounterServlet.java | 2 -- .../src/main/java/com/baeldung/servlets/UppercaseServlet.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/javax-servlets/src/main/java/com/baeldung/servlets/CounterServlet.java b/javax-servlets/src/main/java/com/baeldung/servlets/CounterServlet.java index b9ea55de73..a11f084db2 100644 --- a/javax-servlets/src/main/java/com/baeldung/servlets/CounterServlet.java +++ b/javax-servlets/src/main/java/com/baeldung/servlets/CounterServlet.java @@ -11,8 +11,6 @@ import java.io.PrintWriter; public class CounterServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { - response.setContentType("text/html"); - PrintWriter out = response.getWriter(); int count = (int)request.getServletContext().getAttribute("counter"); diff --git a/javax-servlets/src/main/java/com/baeldung/servlets/UppercaseServlet.java b/javax-servlets/src/main/java/com/baeldung/servlets/UppercaseServlet.java index 0357ab28b5..766ec2e6ff 100644 --- a/javax-servlets/src/main/java/com/baeldung/servlets/UppercaseServlet.java +++ b/javax-servlets/src/main/java/com/baeldung/servlets/UppercaseServlet.java @@ -13,8 +13,6 @@ public class UppercaseServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { String inputString = request.getParameter("input").toUpperCase(); - response.setContentType("text/html"); - PrintWriter out = response.getWriter(); out.println(inputString); From a966ec5aee92c6617b05886850193a64d4c55922 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 23 Feb 2019 23:46:23 +0200 Subject: [PATCH 095/496] Update LazyRequestUnitTest.java --- .../java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java b/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java index 7b461b0769..3830bc52d0 100644 --- a/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java +++ b/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java @@ -14,8 +14,8 @@ public class LazyRequestUnitTest { LazyRequest request = LazyRequestImpl.lazy(() -> mockSupplier.get()); Mockito.verify(mockSupplier, Mockito.times(0)).get(); -// Assert.assertEquals(LazyRequestImpl.getPath(request), "http://test.com/get"); -// Mockito.verify(mockSupplier, Mockito.times(1)).get(); + Assert.assertEquals(LazyRequestImpl.getPath(request), "http://test.com/get"); + Mockito.verify(mockSupplier, Mockito.times(1)).get(); } From 928a23494d5c3ca99d95ab2c8ed13978f01f3da1 Mon Sep 17 00:00:00 2001 From: caroline Date: Sat, 23 Feb 2019 22:49:32 +0100 Subject: [PATCH 096/496] New code for article BAEL-2460. Added maven module spring-cloud-kubernetes-project --- .../client-service/Dockerfile | 12 +++ .../client-service/pom.xml | 71 ++++++++++++++ .../services/client/ClientApplication.java | 96 +++++++++++++++++++ .../services/client/config/ClientConfig.java | 19 ++++ .../client/controller/ClientController.java | 43 +++++++++ .../service/TravelAgencyClientService.java | 45 +++++++++ .../src/main/resources/bootstrap.yml | 6 ++ .../gateway-service/Dockerfile | 12 +++ .../gateway-service/pom.xml | 76 +++++++++++++++ .../services/gateway/GatewayApplication.java | 44 +++++++++ .../src/main/resources/bootstrap.yml | 6 ++ .../spring-cloud-kubernetes-project/pom.xml | 27 ++++++ .../travel-agency-service/Dockerfile | 12 +++ .../travel-agency-service/pom.xml | 59 ++++++++++++ .../travelagency/TravelAgencyApplication.java | 24 +++++ .../controller/TravelAgencyController.java | 36 +++++++ .../src/main/resources/bootstrap.yml | 6 ++ 17 files changed, 594 insertions(+) create mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/Dockerfile create mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/pom.xml create mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/ClientApplication.java create mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/config/ClientConfig.java create mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/controller/ClientController.java create mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/service/TravelAgencyClientService.java create mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/resources/bootstrap.yml create mode 100644 spring-cloud/spring-cloud-kubernetes-project/gateway-service/Dockerfile create mode 100644 spring-cloud/spring-cloud-kubernetes-project/gateway-service/pom.xml create mode 100644 spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/gateway/GatewayApplication.java create mode 100644 spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/resources/bootstrap.yml create mode 100644 spring-cloud/spring-cloud-kubernetes-project/pom.xml create mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/Dockerfile create mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/pom.xml create mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/TravelAgencyApplication.java create mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/controller/TravelAgencyController.java create mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/resources/bootstrap.yml diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes-project/client-service/Dockerfile new file mode 100644 index 0000000000..93e75216db --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/client-service/Dockerfile @@ -0,0 +1,12 @@ +# requires Docker version 17.05.0-ce-rc1, build 2878a85 +FROM maven:3.5-jdk-8 as BUILDAGENCY + +COPY src /usr/src/myapp/src +COPY pom.xml /usr/src/myapp +RUN mvn -f /usr/src/myapp/pom.xml clean package -DskipTests + +FROM openjdk:alpine + +COPY --from=BUILDAGENCY /usr/src/myapp/target/*.jar /maven/ + +CMD java $JAVA_OPTS -jar maven/*.jar \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/pom.xml b/spring-cloud/spring-cloud-kubernetes-project/client-service/pom.xml new file mode 100644 index 0000000000..6bba5512cd --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/client-service/pom.xml @@ -0,0 +1,71 @@ + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.0.6.RELEASE + + client-service + com.baeldung.spring.cloud + 1.0-SNAPSHOT + + + 1.8 + 2.0.1.RELEASE + Finchley.SR2 + 0.3.0.RELEASE + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + org.springframework.cloud + spring-cloud-kubernetes-dependencies + ${spring.cloud.k8s.version} + pom + import + + + + + + + org.springframework.cloud + spring-cloud-kubernetes-discovery + + + org.springframework.cloud + spring-cloud-starter-kubernetes-config + + + org.springframework.cloud + spring-cloud-starter-netflix-hystrix + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/ClientApplication.java b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/ClientApplication.java new file mode 100644 index 0000000000..9044de9574 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/ClientApplication.java @@ -0,0 +1,96 @@ +package com.baeldung.spring.cloud.kubernetes.services.department; + +import com.baeldung.spring.cloud.kubernetes.services.client.config.ClientConfig; +import com.baeldung.spring.cloud.kubernetes.services.client.service.TravelAgencyClientService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.web.client.RestTemplate; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.List; +import java.util.Map; + +@SpringBootApplication +@EnableDiscoveryClient +@EnableCircuitBreaker +public class ClientApplication implements CommandLineRunner { + + private static final Log log = LogFactory.getLog(ClientApplication.class); + private static final String FIND_TRAVEL_DEALS_TASK = "Find new travel deals"; + + @Autowired + private DiscoveryClient discoveryClient; + + @Autowired + private TravelAgencyClientService travelAgencyClient; + + @Autowired + private ClientConfig clientConfig; + + private String task = FIND_TRAVEL_DEALS_TASK; + + @Bean + private RestTemplate restTemplate() { + return new RestTemplate(); + } + + @Value("${spring.application.name}") + private String appName; + + public static void main(String[] args) { + SpringApplication.run(ClientApplication.class, args); + } + + @Override + public void run(String... args) { + log.info("Client (" + appName + ":" + clientConfig.getType() + ")Started! "); + } + + /* + * Every 10 seconds look for new deals + */ + @Scheduled(fixedRate = 10000) + public void doSomeWork() throws UnknownHostException { + if (task.equals(FIND_TRAVEL_DEALS_TASK)) { + task = findNewDeals(); + if (task.equals(FIND_TRAVEL_DEALS_TASK)) { + log.info("NO DEAL FOUND, I will keep looking for one "); + } + } + log.info(">>> Working on " + task); + } + + + + + private String findNewDeals() throws UnknownHostException { + List services = this.discoveryClient.getServices(); + + for (String service : services) { + List instances = this.discoveryClient.getInstances(service); + for (ServiceInstance se : instances) { + Map metadata = se.getMetadata(); + String type = metadata.get("type"); + if ("deal".equals(type)) { + + String from = appName + "@" + InetAddress.getLocalHost().getHostName(); + String url = "http://" + se.getServiceId(); + return travelAgencyClient.requestDeals(url, from); + } + } + } + return FIND_TRAVEL_DEALS_TASK; + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/config/ClientConfig.java b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/config/ClientConfig.java new file mode 100644 index 0000000000..a4f43e2ddc --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/config/ClientConfig.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.cloud.kubernetes.services.client.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "client") +public class ClientConfig { + + private String type = "generic-client"; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/controller/ClientController.java b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/controller/ClientController.java new file mode 100644 index 0000000000..dad736953e --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/controller/ClientController.java @@ -0,0 +1,43 @@ +package com.baeldung.spring.cloud.kubernetes.services.client.controller; + +import java.io.UnsupportedEncodingException; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import com.baeldung.spring.cloud.kubernetes.services.client.config.ClientConfig; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +@RestController +@RefreshScope +public class ClientController { + + private static final Log log = LogFactory.getLog(ClientController.class); + + private enum ClientTravelType { + BUSINESS, + STUDENT, + COUPLE, + FRIENDS, + SINGLE, + FAMILY; + } + + @Autowired + private ClientConfig clientConfig; + + @RequestMapping(method = GET) + public String get() throws UnknownHostException, UnsupportedEncodingException { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Host: ").append(InetAddress.getLocalHost().getHostName()).append("
"); + stringBuilder.append("Client Type: ").append(clientConfig.getType()).append("
"); + stringBuilder.append("IP: ").append(InetAddress.getLocalHost().getHostAddress()).append("
"); + return stringBuilder.toString(); + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/service/TravelAgencyClientService.java b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/service/TravelAgencyClientService.java new file mode 100644 index 0000000000..ba86808cd5 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/service/TravelAgencyClientService.java @@ -0,0 +1,45 @@ +package com.baeldung.spring.cloud.kubernetes.services.client.service; + +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; +import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +public class TravelAgencyClientService { + + private final RestTemplate restTemplate; + + private static final Log log = LogFactory.getLog(TravelAgencyClientService.class); + + public static final String FIND_NEW_TRAVEL_DEALS = "find new travel deals"; + + public TravelAgencyClientService(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + @HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = { + @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000") + }) + public String requestDeals(String to, + String from) { + + String url = String.format("%s/deals/%s", + to, + from); + + log.info("--- Requesting travel deals to travel agency " + url); + + return restTemplate.getForObject(url, String.class); + } + + private String getFallbackName(String to, + String from) { + log.error("--- This travel agency (" + to + ") not available now, please come back later (Fallback) client:" + from); + return FIND_NEW_TRAVEL_DEALS; + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/resources/bootstrap.yml new file mode 100644 index 0000000000..736a17b041 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: client-service + cloud: + config: + uri: http://localhost:8088 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/Dockerfile new file mode 100644 index 0000000000..93e75216db --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/Dockerfile @@ -0,0 +1,12 @@ +# requires Docker version 17.05.0-ce-rc1, build 2878a85 +FROM maven:3.5-jdk-8 as BUILDAGENCY + +COPY src /usr/src/myapp/src +COPY pom.xml /usr/src/myapp +RUN mvn -f /usr/src/myapp/pom.xml clean package -DskipTests + +FROM openjdk:alpine + +COPY --from=BUILDAGENCY /usr/src/myapp/target/*.jar /maven/ + +CMD java $JAVA_OPTS -jar maven/*.jar \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/pom.xml b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/pom.xml new file mode 100644 index 0000000000..84eb353fb9 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/pom.xml @@ -0,0 +1,76 @@ + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.0.6.RELEASE + + gateway-service + com.baeldung.spring.cloud + 1.0-SNAPSHOT + + + 1.8 + 2.0.1.RELEASE + Finchley.SR2 + 0.3.0.RELEASE + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + org.springframework.cloud + spring-cloud-kubernetes-dependencies + ${spring.cloud.k8s.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework.cloud + spring-cloud-starter-netflix-hystrix + + + org.springframework.cloud + spring-cloud-starter-gateway + + + org.springframework.cloud + spring-cloud-kubernetes-discovery + + + org.springframework.cloud + spring-cloud-kubernetes-ribbon + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/gateway/GatewayApplication.java b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/gateway/GatewayApplication.java new file mode 100644 index 0000000000..7f11906aba --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/gateway/GatewayApplication.java @@ -0,0 +1,44 @@ +package com.baeldung.spring.cloud.kubernetes.services.gateway; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator; +import org.springframework.cloud.gateway.discovery.DiscoveryLocatorProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.client.RestTemplate; + +@EnableScheduling +@EnableDiscoveryClient +@SpringBootApplication +public class GatewayApplication { + + private static final Log log = LogFactory.getLog(GatewayApplication.class); + + @Autowired + private DiscoveryClient discoveryClient; + + @Bean + public DiscoveryClientRouteDefinitionLocator discoveryClientRouteLocator(DiscoveryClient discoveryClient, + DiscoveryLocatorProperties properties) { + return new DiscoveryClientRouteDefinitionLocator(discoveryClient, + properties); + } + + public static void main(String[] args) { + SpringApplication.run(GatewayApplication.class, + args); + } + + @LoadBalanced + @Bean + RestTemplate restTemplate() { + return new RestTemplate(); + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/resources/bootstrap.yml new file mode 100644 index 0000000000..5fd607d335 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: gateway-service + cloud: + config: + uri: http://localhost:8088 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/pom.xml b/spring-cloud/spring-cloud-kubernetes-project/pom.xml new file mode 100644 index 0000000000..dc4e3bfe70 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + com.baeldung.spring.cloud + spring-cloud-kubernetes-project + 1.0.0-SNAPSHOT + spring-cloud-kubernetes-project + Spring Cloud Kubernetes + pom + + + travel-agency-service + client-service + gateway-service + + + + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT + .. + + + + + diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/Dockerfile new file mode 100644 index 0000000000..93e75216db --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/Dockerfile @@ -0,0 +1,12 @@ +# requires Docker version 17.05.0-ce-rc1, build 2878a85 +FROM maven:3.5-jdk-8 as BUILDAGENCY + +COPY src /usr/src/myapp/src +COPY pom.xml /usr/src/myapp +RUN mvn -f /usr/src/myapp/pom.xml clean package -DskipTests + +FROM openjdk:alpine + +COPY --from=BUILDAGENCY /usr/src/myapp/target/*.jar /maven/ + +CMD java $JAVA_OPTS -jar maven/*.jar \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/pom.xml b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/pom.xml new file mode 100644 index 0000000000..69cd22ae52 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/pom.xml @@ -0,0 +1,59 @@ + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.0.6.RELEASE + + travel-agency-service + com.baeldung.spring.cloud + 1.0-SNAPSHOT + + + 1.8 + 2.0.1.RELEASE + Finchley.SR2 + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-actuator + + + org.springframework.boot + spring-boot-actuator-autoconfigure + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/TravelAgencyApplication.java b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/TravelAgencyApplication.java new file mode 100644 index 0000000000..c96b547e18 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/TravelAgencyApplication.java @@ -0,0 +1,24 @@ +package com.baeldung.spring.cloud.kubernetes.services.department; + +import com.baeldung.spring.cloud.kubernetes.services.travelagency.controller.TravelAgencyController; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TravelAgencyApplication implements CommandLineRunner { + + private static final Log log = LogFactory.getLog(TravelAgencyController.class); + + public static void main(String[] args) { + SpringApplication.run(TravelAgencyApplication.class, args); + } + + @Override + public void run(String... args) throws Exception { + log.info("Travel Agency Started! "); + } + +} diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/controller/TravelAgencyController.java b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/controller/TravelAgencyController.java new file mode 100644 index 0000000000..ec84debe83 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/controller/TravelAgencyController.java @@ -0,0 +1,36 @@ +package com.baeldung.spring.cloud.kubernetes.services.travelagency.controller; + +import org.springframework.web.bind.annotation.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Random; +import static org.springframework.web.bind.annotation.RequestMethod.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +@RestController +public class TravelAgencyController { + + private String[] deals = {"London - Paris : 25 Euro", "London - Frankfurt : 25 Euro"}; + private static final Log log = LogFactory.getLog(TravelAgencyController.class); + + + @RequestMapping(method = POST, path = "/deals/{client}") + public String deals(@PathVariable("client") String client) { + log.info("Client: " + client + " is requesting new deals!"); + int randomDeal = new Random().nextInt(deals.length); + return deals[randomDeal]; + } + + @RequestMapping(method = GET, path = "/") + @ResponseBody + public String get() throws UnknownHostException { + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Host: ").append(InetAddress.getLocalHost().getHostName()).append("
"); + stringBuilder.append("IP: ").append(InetAddress.getLocalHost().getHostAddress()).append("
"); + stringBuilder.append("Type: ").append("Travel Agency").append("
"); + return stringBuilder.toString(); + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/resources/bootstrap.yml new file mode 100644 index 0000000000..d9fd0c0e76 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/resources/bootstrap.yml @@ -0,0 +1,6 @@ +spring: + application: + name: travelagency-service + cloud: + config: + uri: http://localhost:8088 \ No newline at end of file From ca4440d7925b295813e26dee7583f468f9ca617f Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Sat, 23 Feb 2019 23:20:37 -0300 Subject: [PATCH 097/496] Guide to Stream.reduce() (#6372) * Initial Commit * Update StreamReduceUnitTest.java * Update StreamReduceUnitTest.java * Update StreamReduceUnitTest.java --- .../streamreduce/application/Application.java | 62 +++++++++ .../baeldung/streamreduce/entities/User.java | 25 ++++ .../streamreduce/utilities/NumberUtils.java | 52 ++++++++ .../tests/StreamReduceUnitTest.java | 126 ++++++++++++++++++ 4 files changed, 265 insertions(+) create mode 100644 core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java create mode 100644 core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java create mode 100644 core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java create mode 100644 core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceUnitTest.java diff --git a/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java b/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java new file mode 100644 index 0000000000..0b1dd952dc --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/streamreduce/application/Application.java @@ -0,0 +1,62 @@ +package com.baeldung.streamreduce.application; + +import com.baeldung.streamreduce.entities.User; +import com.baeldung.streamreduce.utilities.NumberUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Application { + + public static void main(String[] args) { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result1 = numbers.stream().reduce(0, (a, b) -> a + b); + System.out.println(result1); + + int result2 = numbers.stream().reduce(0, Integer::sum); + System.out.println(result2); + + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result3 = letters.stream().reduce("", (a, b) -> a + b); + System.out.println(result3); + + String result4 = letters.stream().reduce("", String::concat); + System.out.println(result4); + + String result5 = letters.stream().reduce("", (a, b) -> a.toUpperCase() + b.toUpperCase()); + System.out.println(result5); + + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + int result6 = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result6); + + String result7 = letters.parallelStream().reduce("", String::concat); + System.out.println(result7); + + int result8 = users.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result8); + + List userList = new ArrayList<>(); + for (int i = 0; i <= 1000000; i++) { + userList.add(new User("John" + i, i)); + } + + long t1 = System.currentTimeMillis(); + int result9 = userList.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + long t2 = System.currentTimeMillis(); + System.out.println(result9); + System.out.println("Sequential stream time: " + (t2 - t1) + "ms"); + + long t3 = System.currentTimeMillis(); + int result10 = userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + long t4 = System.currentTimeMillis(); + System.out.println(result10); + System.out.println("Parallel stream time: " + (t4 - t3) + "ms"); + + int result11 = NumberUtils.divideListElements(numbers, 1); + System.out.println(result11); + + int result12 = NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 0); + System.out.println(result12); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java b/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java new file mode 100644 index 0000000000..bc13a8cde6 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/streamreduce/entities/User.java @@ -0,0 +1,25 @@ +package com.baeldung.streamreduce.entities; + +public class User { + + private final String name; + private final int age; + + public User(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return "User{" + "name=" + name + ", age=" + age + '}'; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java b/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java new file mode 100644 index 0000000000..7a6a85e6c4 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/streamreduce/utilities/NumberUtils.java @@ -0,0 +1,52 @@ +package com.baeldung.streamreduce.utilities; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.logging.Level; +import java.util.logging.Logger; + +public abstract class NumberUtils { + + private static final Logger LOGGER = Logger.getLogger(NumberUtils.class.getName()); + + public static int divideListElements(List values, Integer divider) { + return values.stream() + .reduce(0, (a, b) -> { + try { + return a / divider + b / divider; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return 0; + }); + } + + public static int divideListElementsWithExtractedTryCatchBlock(List values, int divider) { + return values.stream().reduce(0, (a, b) -> divide(a, divider) + divide(b, divider)); + } + + public static int divideListElementsWithApplyFunctionMethod(List values, int divider) { + BiFunction division = (a, b) -> a / b; + return values.stream().reduce(0, (a, b) -> applyFunction(division, a, divider) + applyFunction(division, b, divider)); + } + + private static int divide(int value, int factor) { + int result = 0; + try { + result = value / factor; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return result; + } + + private static int applyFunction(BiFunction function, int a, int b) { + try { + return function.apply(a, b); + } + catch(Exception e) { + LOGGER.log(Level.INFO, "Exception occurred!"); + } + return 0; + } +} diff --git a/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceUnitTest.java b/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceUnitTest.java new file mode 100644 index 0000000000..7a50592164 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceUnitTest.java @@ -0,0 +1,126 @@ +package com.baeldung.streamreduce.tests; + +import com.baeldung.streamreduce.entities.User; +import com.baeldung.streamreduce.utilities.NumberUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class StreamReduceUnitTest { + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorLambda_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + int result = numbers.stream().reduce(0, (a, b) -> a + b); + + assertThat(result).isEqualTo(21); + } + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorMethodReference_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + int result = numbers.stream().reduce(0, Integer::sum); + + assertThat(result).isEqualTo(21); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorLambda_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + + String result = letters.stream().reduce("", (a, b) -> a + b); + + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorMethodReference_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + + String result = letters.stream().reduce("", String::concat); + + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithUppercaseConcatenatorAccumulator_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + + String result = letters.stream().reduce("", (a, b) -> a.toUpperCase() + b.toUpperCase()); + + assertThat(result).isEqualTo("ABCDE"); + } + + @Test + public void givenUserList_whenReduceWithAgeAccumulatorAndSumCombiner_thenCorrect() { + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + + int result = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + + assertThat(result).isEqualTo(65); + } + + @Test + public void givenStringList_whenReduceWithParallelStream_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + + String result = letters.parallelStream().reduce("", String::concat); + + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElements_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElements(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlock_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlockAndListContainsZero_thenCorrect() { + List numbers = Arrays.asList(0, 1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlockAndDividerIsZero_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 0)).isEqualTo(0); + } + + @Test + public void givenStream_whneCalleddivideListElementsWithApplyFunctionMethod_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + + assertThat(NumberUtils.divideListElementsWithApplyFunctionMethod(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenTwoStreams_whenCalledReduceOnParallelizedStream_thenFasterExecutionTime() { + List userList = new ArrayList<>(); + for (int i = 0; i <= 1000000; i++) { + userList.add(new User("John" + i, i)); + } + long currentTime1 = System.currentTimeMillis(); + userList.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + long sequentialExecutionTime = System.currentTimeMillis() -currentTime1; + long currentTime2 = System.currentTimeMillis(); + userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + long parallelizedExecutionTime = System.currentTimeMillis() - currentTime2; + + assertThat(parallelizedExecutionTime).isLessThan(sequentialExecutionTime); + } +} From a7e3fcdd3ece3050870bfa383e864e50aee11179 Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 24 Feb 2019 08:31:54 +0200 Subject: [PATCH 098/496] add libraries to default profile --- libraries/pom.xml | 4 ++-- pom.xml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/pom.xml b/libraries/pom.xml index a9af996740..a6ff9e6a80 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -698,7 +698,7 @@ reflections ${reflections.version}
-
+ @@ -920,4 +920,4 @@ - \ No newline at end of file + diff --git a/pom.xml b/pom.xml index b4bab0a389..4d4cd574d7 100644 --- a/pom.xml +++ b/pom.xml @@ -475,6 +475,7 @@ kotlin-libraries + libraries libraries-data libraries-apache-commons libraries-security From 56c7ea955d62fa32039ba33df08e8fcdb17f2bec Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 24 Feb 2019 09:09:41 +0200 Subject: [PATCH 099/496] rename failing test --- .../{StreamReduceUnitTest.java => StreamReduceManualTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename core-java-8/src/test/java/com/baeldung/streamreduce/tests/{StreamReduceUnitTest.java => StreamReduceManualTest.java} (96%) diff --git a/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceUnitTest.java b/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java similarity index 96% rename from core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceUnitTest.java rename to core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java index 7a50592164..9222cbb689 100644 --- a/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/streamreduce/tests/StreamReduceManualTest.java @@ -8,7 +8,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; -public class StreamReduceUnitTest { +public class StreamReduceManualTest { @Test public void givenIntegerList_whenReduceWithSumAccumulatorLambda_thenCorrect() { From 89e39c37cba71b86e846f913e4389f79385d5893 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 24 Feb 2019 17:02:52 +0530 Subject: [PATCH 100/496] [BAEL-12666] - POM Properties Cleanup --- akka-http/pom.xml | 1 - algorithms-genetic/pom.xml | 1 - algorithms-miscellaneous-1/pom.xml | 1 - algorithms-miscellaneous-2/pom.xml | 1 - algorithms-sorting/pom.xml | 1 - apache-avro/pom.xml | 1 - apache-curator/pom.xml | 3 +-- apache-geode/pom.xml | 6 ++---- apache-spark/pom.xml | 6 ++---- azure/pom.xml | 1 - cdi/pom.xml | 1 - core-java-8/pom.xml | 1 - core-java-arrays/pom.xml | 1 - core-java-collections-list/pom.xml | 1 - core-java-collections/pom.xml | 1 - core-java-io/pom.xml | 3 --- core-java-lang-oop/pom.xml | 1 - core-java-lang/pom.xml | 4 ---- core-java-sun/pom.xml | 3 --- core-java/pom.xml | 2 -- couchbase/pom.xml | 3 +-- ethereum/pom.xml | 3 --- feign/pom.xml | 1 - jackson/pom.xml | 2 -- java-dates/pom.xml | 1 - java-ee-8-security-api/pom.xml | 14 +++++++------- java-lite/pom.xml | 1 - java-streams/pom.xml | 1 - javaxval/pom.xml | 3 +-- jib/pom.xml | 1 - json/pom.xml | 4 +--- libraries-data/pom.xml | 1 - libraries-security/pom.xml | 1 - libraries-server/pom.xml | 1 - libraries/pom.xml | 1 - parent-spring-5/pom.xml | 1 - pom.xml | 3 ++- rest-with-spark-java/pom.xml | 6 ++---- spring-core/pom.xml | 1 - spring-dispatcher-servlet/pom.xml | 2 +- spring-integration/pom.xml | 1 - spring-mvc-forms-jsp/pom.xml | 2 +- spring-mvc-java/pom.xml | 2 +- spring-security-mvc-custom/pom.xml | 4 ++-- spring-security-rest-basic-auth/pom.xml | 2 +- 45 files changed, 25 insertions(+), 77 deletions(-) diff --git a/akka-http/pom.xml b/akka-http/pom.xml index 05e50d2229..6d73f2f2e6 100644 --- a/akka-http/pom.xml +++ b/akka-http/pom.xml @@ -41,7 +41,6 @@ UTF-8 UTF-8 - 1.8 10.0.11 2.5.11 diff --git a/algorithms-genetic/pom.xml b/algorithms-genetic/pom.xml index fc6d36dac1..56f6a31525 100644 --- a/algorithms-genetic/pom.xml +++ b/algorithms-genetic/pom.xml @@ -54,7 +54,6 @@ - 1.16.12 3.6.1 3.7.0 3.9.0 diff --git a/algorithms-miscellaneous-1/pom.xml b/algorithms-miscellaneous-1/pom.xml index 5006670dd9..fe670963c0 100644 --- a/algorithms-miscellaneous-1/pom.xml +++ b/algorithms-miscellaneous-1/pom.xml @@ -74,7 +74,6 @@ - 1.16.12 3.6.1 3.9.0 1.11 diff --git a/algorithms-miscellaneous-2/pom.xml b/algorithms-miscellaneous-2/pom.xml index d5f3172eaa..e85dd456a3 100644 --- a/algorithms-miscellaneous-2/pom.xml +++ b/algorithms-miscellaneous-2/pom.xml @@ -84,7 +84,6 @@ - 1.16.12 3.6.1 1.0.1 1.0.1 diff --git a/algorithms-sorting/pom.xml b/algorithms-sorting/pom.xml index 2aee6e9199..b25adf05a8 100644 --- a/algorithms-sorting/pom.xml +++ b/algorithms-sorting/pom.xml @@ -49,7 +49,6 @@ - 1.16.12 3.6.1 3.9.0 1.11 diff --git a/apache-avro/pom.xml b/apache-avro/pom.xml index b98e52be75..5d170f0a81 100644 --- a/apache-avro/pom.xml +++ b/apache-avro/pom.xml @@ -82,7 +82,6 @@ UTF-8 3.5 1.8.2 - 1.8 1.7.25 diff --git a/apache-curator/pom.xml b/apache-curator/pom.xml index 3306c0613f..259319d547 100644 --- a/apache-curator/pom.xml +++ b/apache-curator/pom.xml @@ -39,7 +39,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-databind.version} + ${jackson.version} @@ -59,7 +59,6 @@ 4.0.1 3.4.11 - 2.9.7 3.6.1 1.7.0 diff --git a/apache-geode/pom.xml b/apache-geode/pom.xml index a39e4a811e..15c7e04d29 100644 --- a/apache-geode/pom.xml +++ b/apache-geode/pom.xml @@ -32,8 +32,8 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven.compiler.source} - ${maven.compiler.target} + ${java.version} + ${java.version} @@ -41,7 +41,5 @@ 1.6.0 - 1.8 - 1.8 \ No newline at end of file diff --git a/apache-spark/pom.xml b/apache-spark/pom.xml index 1aed5b1db9..f0f002a7e9 100644 --- a/apache-spark/pom.xml +++ b/apache-spark/pom.xml @@ -56,8 +56,8 @@ maven-compiler-plugin ${maven-compiler-plugin.version} - ${maven.compiler.source} - ${maven.compiler.target} + ${java.version} + ${java.version} @@ -85,8 +85,6 @@ 2.3.0 2.3.0 1.5.2 - 1.8 - 1.8 3.2 diff --git a/azure/pom.xml b/azure/pom.xml index e2a05796d6..270b3e4829 100644 --- a/azure/pom.xml +++ b/azure/pom.xml @@ -127,7 +127,6 @@ ${azure.containerRegistry}.azurecr.io 1.1.0 1.1.0 - 1.8 diff --git a/cdi/pom.xml b/cdi/pom.xml index ba649127a0..85da8518d0 100644 --- a/cdi/pom.xml +++ b/cdi/pom.xml @@ -66,7 +66,6 @@ 1.9.2 1.3 3.10.0 - 4.12 5.1.2.RELEASE diff --git a/core-java-8/pom.xml b/core-java-8/pom.xml index b4519a8161..b63afef7d4 100644 --- a/core-java-8/pom.xml +++ b/core-java-8/pom.xml @@ -180,7 +180,6 @@ 4.1 4.01 1.10 - 1.16.12 0.9.0 1.13 2.10 diff --git a/core-java-arrays/pom.xml b/core-java-arrays/pom.xml index 39ac764b27..ac9f7d08f0 100644 --- a/core-java-arrays/pom.xml +++ b/core-java-arrays/pom.xml @@ -390,7 +390,6 @@ 3.8.1 - 1.16.12 1.19 1.19 diff --git a/core-java-collections-list/pom.xml b/core-java-collections-list/pom.xml index b9b6f4a6a6..217278bdf6 100644 --- a/core-java-collections-list/pom.xml +++ b/core-java-collections-list/pom.xml @@ -70,7 +70,6 @@ 3.8.1 1.7.0 3.11.1 - 1.16.12 3.0.2 8.1.0 1.2.0 diff --git a/core-java-collections/pom.xml b/core-java-collections/pom.xml index 261558836d..b791f38b24 100644 --- a/core-java-collections/pom.xml +++ b/core-java-collections/pom.xml @@ -73,7 +73,6 @@ 1.7.0 3.11.1 7.1.0 - 1.16.12 1.3 diff --git a/core-java-io/pom.xml b/core-java-io/pom.xml index 350e1a8b96..b6f8a317f6 100644 --- a/core-java-io/pom.xml +++ b/core-java-io/pom.xml @@ -246,8 +246,6 @@ - - 2.9.7 3.5 @@ -259,7 +257,6 @@ 4.01 0.4 1.8.7 - 1.16.12 4.6-b01 1.13 0.6.5 diff --git a/core-java-lang-oop/pom.xml b/core-java-lang-oop/pom.xml index 8cfaf2b544..6763bbb26d 100644 --- a/core-java-lang-oop/pom.xml +++ b/core-java-lang-oop/pom.xml @@ -82,7 +82,6 @@ 3.5 - 1.16.12 3.10.0 3.0.3 diff --git a/core-java-lang/pom.xml b/core-java-lang/pom.xml index 6881fd56db..551c8e8505 100644 --- a/core-java-lang/pom.xml +++ b/core-java-lang/pom.xml @@ -74,14 +74,10 @@ - - - 2.9.7 2.8.2 3.5 - 1.16.12 1.5.0-b01 diff --git a/core-java-sun/pom.xml b/core-java-sun/pom.xml index 6099e7a5ac..5f2065016f 100644 --- a/core-java-sun/pom.xml +++ b/core-java-sun/pom.xml @@ -261,8 +261,6 @@ - - 2.9.7 23.0 @@ -275,7 +273,6 @@ 4.01 0.4 1.8.7 - 1.16.12 4.6-b01 1.13 0.6.5 diff --git a/core-java/pom.xml b/core-java/pom.xml index d21c624997..463b65a4ce 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -451,7 +451,6 @@ - 2.9.7 2.8.2 @@ -461,7 +460,6 @@ 1.0.3 0.4 1.8.7 - 1.16.12 4.6-b01 1.13 0.6.5 diff --git a/couchbase/pom.xml b/couchbase/pom.xml index 994b80e7cd..31e6a53388 100644 --- a/couchbase/pom.xml +++ b/couchbase/pom.xml @@ -25,7 +25,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-version} + ${jackson.version} @@ -70,7 +70,6 @@ 2.5.0 4.3.5.RELEASE 3.5 - 2.9.7 diff --git a/ethereum/pom.xml b/ethereum/pom.xml index c7f82eaf22..baa74b58a5 100644 --- a/ethereum/pom.xml +++ b/ethereum/pom.xml @@ -208,15 +208,12 @@ UTF-8 - 1.8 8.5.4 1.5.0-RELEASE 3.3.1 1.5.6.RELEASE 2.21.0 - 2.9.7 1.3 - 2.9.7 2.3.1 3.1.0 2.4.0 diff --git a/feign/pom.xml b/feign/pom.xml index ea645383c1..d2fa334270 100644 --- a/feign/pom.xml +++ b/feign/pom.xml @@ -56,7 +56,6 @@ 9.4.0 - 1.16.12 1.4.2.RELEASE diff --git a/jackson/pom.xml b/jackson/pom.xml index e941ababc5..948248d255 100644 --- a/jackson/pom.xml +++ b/jackson/pom.xml @@ -117,8 +117,6 @@ - - 2.9.7 3.8 2.10 diff --git a/java-dates/pom.xml b/java-dates/pom.xml index 8dd5ad675e..d4f690d894 100644 --- a/java-dates/pom.xml +++ b/java-dates/pom.xml @@ -76,7 +76,6 @@ 3.5 - 1.16.12 2.10 3.6.1 diff --git a/java-ee-8-security-api/pom.xml b/java-ee-8-security-api/pom.xml index ad33c74ad3..0cce84e5f2 100644 --- a/java-ee-8-security-api/pom.xml +++ b/java-ee-8-security-api/pom.xml @@ -58,6 +58,13 @@ + + app-auth-basic-store-db + app-auth-form-store-ldap + app-auth-custom-form-store-custom + app-auth-custom-no-store + + 9080 9443 @@ -70,11 +77,4 @@ 3.2.2 - - app-auth-basic-store-db - app-auth-form-store-ldap - app-auth-custom-form-store-custom - app-auth-custom-no-store - - diff --git a/java-lite/pom.xml b/java-lite/pom.xml index b261e521a1..ce6e838d92 100644 --- a/java-lite/pom.xml +++ b/java-lite/pom.xml @@ -95,7 +95,6 @@ 1.15 5.1.45 1.7.0 - 2.9.7 1.15 diff --git a/java-streams/pom.xml b/java-streams/pom.xml index 0de1a424d6..00384eeead 100644 --- a/java-streams/pom.xml +++ b/java-streams/pom.xml @@ -108,7 +108,6 @@ 1.21 3.5 - 1.16.12 0.9.0 1.15 0.6.5 diff --git a/javaxval/pom.xml b/javaxval/pom.xml index f31aa0dc77..7ecddc0ca8 100644 --- a/javaxval/pom.xml +++ b/javaxval/pom.xml @@ -55,8 +55,7 @@ 2.0.1.Final 6.0.13.Final 3.0.0 - 5.0.2.RELEASE - 4.12 + 5.0.2.RELEASE 3.11.1 diff --git a/jib/pom.xml b/jib/pom.xml index 5c9f242a20..2341fcca0c 100644 --- a/jib/pom.xml +++ b/jib/pom.xml @@ -39,7 +39,6 @@ - 1.8 0.9.10 diff --git a/json/pom.xml b/json/pom.xml index 7a6d57c28e..c76625a6fa 100644 --- a/json/pom.xml +++ b/json/pom.xml @@ -42,7 +42,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-databind.version} + ${jackson.version} javax.json.bind @@ -89,8 +89,6 @@ 1.0.1 20171018 2.8.5 - 2.9.7 - 4.12 1.1.2 3.11.1 diff --git a/libraries-data/pom.xml b/libraries-data/pom.xml index daf6c8b500..85be66c067 100644 --- a/libraries-data/pom.xml +++ b/libraries-data/pom.xml @@ -434,7 +434,6 @@ 4.0.1 1.4.196 16.5.1 - 4.12 3.7.0 5.0 1.0.0 diff --git a/libraries-security/pom.xml b/libraries-security/pom.xml index ba51227ce0..9f125361ba 100644 --- a/libraries-security/pom.xml +++ b/libraries-security/pom.xml @@ -51,7 +51,6 @@ - 4.12 2.0.4.RELEASE 5.6.0 2.3.3.RELEASE diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml index b30b6137a1..a6ead8fb31 100644 --- a/libraries-server/pom.xml +++ b/libraries-server/pom.xml @@ -105,7 +105,6 @@ 9.4.8.v20171121 4.1.20.Final 4.1 - 4.12 8.5.24 4.3.1 1.2.0 diff --git a/libraries/pom.xml b/libraries/pom.xml index a6ff9e6a80..7823732224 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -845,7 +845,6 @@ 1.9.0 1.9.27 1.1.0 - 4.12 0.10 3.5.0 3.0.0 diff --git a/parent-spring-5/pom.xml b/parent-spring-5/pom.xml index 650305b7e2..5d7a3b66b3 100644 --- a/parent-spring-5/pom.xml +++ b/parent-spring-5/pom.xml @@ -31,7 +31,6 @@ 5.1.2.RELEASE 5.0.2 - 2.9.6 2.9.6 5.1.2.RELEASE diff --git a/pom.xml b/pom.xml index 4d4cd574d7..976c3228d0 100644 --- a/pom.xml +++ b/pom.xml @@ -1630,7 +1630,7 @@ 2.3.1 1.9.13 1.2 - 2.9.7 + 2.9.7 1.3 1.2.0 5.2.0 @@ -1641,5 +1641,6 @@ 2.3 3.8 + 1.16.12 diff --git a/rest-with-spark-java/pom.xml b/rest-with-spark-java/pom.xml index f7c91f8827..fc78ac6b86 100644 --- a/rest-with-spark-java/pom.xml +++ b/rest-with-spark-java/pom.xml @@ -23,19 +23,17 @@ com.fasterxml.jackson.core jackson-core - ${jackson-core.version} + ${jackson.version} com.fasterxml.jackson.core jackson-databind - ${jackson-databind.version} + ${jackson.version} 2.5.4 - 2.9.7 - 2.9.7 diff --git a/spring-core/pom.xml b/spring-core/pom.xml index 46f777c020..d348d742e7 100644 --- a/spring-core/pom.xml +++ b/spring-core/pom.xml @@ -82,7 +82,6 @@ 1 20.0 2.6 - 1.16.12 2.5 1.5.2.RELEASE 1.10.19 diff --git a/spring-dispatcher-servlet/pom.xml b/spring-dispatcher-servlet/pom.xml index 2eeb37eef0..eb0fdfea46 100644 --- a/spring-dispatcher-servlet/pom.xml +++ b/spring-dispatcher-servlet/pom.xml @@ -54,7 +54,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-databind.version} + ${jackson.version} commons-fileupload diff --git a/spring-integration/pom.xml b/spring-integration/pom.xml index 11a1e617aa..367d25de98 100644 --- a/spring-integration/pom.xml +++ b/spring-integration/pom.xml @@ -110,7 +110,6 @@ 1.1.4.RELEASE 1.4.7 1.1.1 - 4.12 2.10 1.5.0 diff --git a/spring-mvc-forms-jsp/pom.xml b/spring-mvc-forms-jsp/pom.xml index 5536314086..e0539c3216 100644 --- a/spring-mvc-forms-jsp/pom.xml +++ b/spring-mvc-forms-jsp/pom.xml @@ -61,7 +61,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-databind.version} + ${jackson.version} org.springframework.boot diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml index 552f62d9f7..853d8db64c 100644 --- a/spring-mvc-java/pom.xml +++ b/spring-mvc-java/pom.xml @@ -40,7 +40,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-databind.version} + ${jackson.version} diff --git a/spring-security-mvc-custom/pom.xml b/spring-security-mvc-custom/pom.xml index 12520a0d01..b4239fb2b8 100644 --- a/spring-security-mvc-custom/pom.xml +++ b/spring-security-mvc-custom/pom.xml @@ -117,7 +117,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-databind.version} + ${jackson.version} @@ -202,7 +202,7 @@ 19.0 3.5 - 2.9.7 + 2.9.7 2.6 diff --git a/spring-security-rest-basic-auth/pom.xml b/spring-security-rest-basic-auth/pom.xml index 61a144db0c..ca5c4c38e6 100644 --- a/spring-security-rest-basic-auth/pom.xml +++ b/spring-security-rest-basic-auth/pom.xml @@ -96,7 +96,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-databind.version} + ${jackson.version} From 52b164ffcaaa7e21d5ccb75d30159b7eb3b38672 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Sat, 23 Feb 2019 14:49:01 -0300 Subject: [PATCH 101/496] [BAEL-11597] Move and update Etags article * Moved etags article related code * Fixed existing etag Ignored test * Added etag scentsio adding etag support to a single endpoint * Added tests for single endpoint etag scenario * Cleaned now unused code in spring-rest-full module --- spring-boot-rest/README.md | 1 + .../com/baeldung/persistence/model/Foo.java | 12 ++ .../java/com/baeldung/spring/WebConfig.java | 11 ++ .../web/controller/FooController.java | 13 ++ .../src/main/resources/WEB-INF/web.xml | 18 +++ .../common/web/AbstractBasicLiveTest.java | 84 ++++++++++++- ...ooControllerCustomEtagIntegrationTest.java | 116 ++++++++++++++++++ .../baeldung/web/LiveTestSuiteLiveTest.java | 4 +- spring-rest-full/README.md | 1 - .../java/org/baeldung/spring/Application.java | 6 - .../web/controller/FooController.java | 8 -- .../hateoas/event/ResourceCreatedEvent.java | 28 ----- ...esourceCreatedDiscoverabilityListener.java | 36 ------ .../src/main/webapp/WEB-INF/web.xml | 9 -- .../java/org/baeldung/TestSuiteLiveTest.java | 16 --- .../common/web/AbstractBasicLiveTest.java | 100 --------------- .../java/org/baeldung/web/FooLiveTest.java | 35 ------ .../baeldung/web/LiveTestSuiteLiveTest.java | 13 -- 18 files changed, 256 insertions(+), 255 deletions(-) create mode 100644 spring-boot-rest/src/main/resources/WEB-INF/web.xml create mode 100644 spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java delete mode 100644 spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/ResourceCreatedEvent.java delete mode 100644 spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java delete mode 100644 spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java delete mode 100644 spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java delete mode 100644 spring-rest-full/src/test/java/org/baeldung/web/FooLiveTest.java delete mode 100644 spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 447dd07159..a0adc5a51f 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -8,3 +8,4 @@ Module for the articles that are part of the Spring REST E-book: 6. [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability) 7. [Versioning a REST API](http://www.baeldung.com/rest-versioning) 8. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) +9. [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java index f19d1c0e0b..c8af731bc5 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Foo.java @@ -7,6 +7,7 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.Version; import com.thoughtworks.xstream.annotations.XStreamAlias; @@ -20,6 +21,9 @@ public class Foo implements Serializable { @Column(nullable = false) private String name; + + @Version + private long version; public Foo() { super(); @@ -49,6 +53,14 @@ public class Foo implements Serializable { this.name = name; } + public long getVersion() { + return version; + } + + public void setVersion(long version) { + this.version = version; + } + // @Override diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index f581e4ec10..d5559bfae7 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -9,6 +9,7 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; import org.springframework.oxm.xstream.XStreamMarshaller; +import org.springframework.web.filter.ShallowEtagHeaderFilter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @@ -45,5 +46,15 @@ public class WebConfig implements WebMvcConfigurer { // // return xmlConverter; // } + + + // Etags + + // If we're not using Spring Boot we can make use of + // AbstractAnnotationConfigDispatcherServletInitializer#getServletFilters + @Bean + public ShallowEtagHeaderFilter shallowEtagHeaderFilter() { + return new ShallowEtagHeaderFilter(); + } } \ No newline at end of file diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java index 59e33263db..255fcaabb7 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java @@ -9,6 +9,7 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -45,6 +46,18 @@ public class FooController { } // API + + // Note: the global filter overrides the ETag value we set here. We can still analyze its behaviour in the Integration Test. + @GetMapping(value = "/{id}/custom-etag") + public ResponseEntity findByIdWithCustomEtag(@PathVariable("id") final Long id, + final HttpServletResponse response) { + final Foo resourceById = RestPreconditions.checkFound(service.findOne(id)); + + eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response)); + return ResponseEntity.ok() + .eTag(Long.toString(resourceById.getVersion())) + .body(resourceById); + } // read - one diff --git a/spring-boot-rest/src/main/resources/WEB-INF/web.xml b/spring-boot-rest/src/main/resources/WEB-INF/web.xml new file mode 100644 index 0000000000..7f36b33b38 --- /dev/null +++ b/spring-boot-rest/src/main/resources/WEB-INF/web.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java index 61eb9400cc..ecf938be50 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractBasicLiveTest.java @@ -1,21 +1,28 @@ package com.baeldung.common.web; import static com.baeldung.web.util.HTTPLinkHeaderUtil.extractURIByRel; +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; +import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import java.io.Serializable; import java.util.List; +import org.junit.Ignore; import org.junit.Test; +import com.baeldung.persistence.model.Foo; import com.google.common.net.HttpHeaders; import io.restassured.RestAssured; +import io.restassured.http.ContentType; import io.restassured.response.Response; public abstract class AbstractBasicLiveTest extends AbstractLiveTest { @@ -97,7 +104,82 @@ public abstract class AbstractBasicLiveTest extends Abst final String uriToNextPage = extractURIByRel(response.getHeader(HttpHeaders.LINK), "next"); assertNull(uriToNextPage); } + + // etags - // count + @Test + public void givenResourceExists_whenRetrievingResource_thenEtagIsAlsoReturned() { + // Given + final String uriOfResource = createAsUri(); + + // When + final Response findOneResponse = RestAssured.given() + .header("Accept", "application/json") + .get(uriOfResource); + + // Then + assertNotNull(findOneResponse.getHeader(HttpHeaders.ETAG)); + } + + @Test + public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() { + // Given + final String uriOfResource = createAsUri(); + final Response findOneResponse = RestAssured.given() + .header("Accept", "application/json") + .get(uriOfResource); + final String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG); + + // When + final Response secondFindOneResponse = RestAssured.given() + .header("Accept", "application/json") + .headers("If-None-Match", etagValue) + .get(uriOfResource); + + // Then + assertTrue(secondFindOneResponse.getStatusCode() == 304); + } + + @Test + public void givenResourceWasRetrievedThenModified_whenRetrievingAgainWithEtag_thenResourceIsReturned() { + // Given + final String uriOfResource = createAsUri(); + final Response firstFindOneResponse = RestAssured.given() + .header("Accept", "application/json") + .get(uriOfResource); + final String etagValue = firstFindOneResponse.getHeader(HttpHeaders.ETAG); + final long createdId = firstFindOneResponse.jsonPath().getLong("id"); + + Foo updatedFoo = new Foo("updated value"); + updatedFoo.setId(createdId); + Response updatedResponse = RestAssured.given().contentType(ContentType.JSON).body(updatedFoo) + .put(uriOfResource); + assertThat(updatedResponse.getStatusCode() == 200); + + // When + final Response secondFindOneResponse = RestAssured.given() + .header("Accept", "application/json") + .headers("If-None-Match", etagValue) + .get(uriOfResource); + + // Then + assertTrue(secondFindOneResponse.getStatusCode() == 200); + } + + @Test + @Ignore("Not Yet Implemented By Spring - https://jira.springsource.org/browse/SPR-10164") + public void givenResourceExists_whenRetrievedWithIfMatchIncorrectEtag_then412IsReceived() { + // Given + final String uriOfResource = createAsUri(); + + // When + final Response findOneResponse = RestAssured.given() + .header("Accept", "application/json") + .headers("If-Match", randomAlphabetic(8)) + .get(uriOfResource); + + // Then + assertTrue(findOneResponse.getStatusCode() == 412); + } } diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java new file mode 100644 index 0000000000..dc48c21b30 --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java @@ -0,0 +1,116 @@ +package com.baeldung.web; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; + +import com.baeldung.persistence.model.Foo; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.net.HttpHeaders; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc(addFilters = false) +public class FooControllerCustomEtagIntegrationTest { + + @Autowired + private MockMvc mvc; + + private String FOOS_ENDPOINT = "/auth/foos/"; + private String CUSTOM_ETAG_ENDPOINT_SUFFIX = "/custom-etag"; + + private static String serializeFoo(Foo foo) throws Exception { + ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(foo); + } + + private static String createFooJson() throws Exception { + return serializeFoo(new Foo(randomAlphabetic(6))); + } + + private static Foo deserializeFoo(String fooJson) throws Exception { + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(fooJson, Foo.class); + } + + @Test + public void givenResourceExists_whenRetrievingResourceUsingCustomEtagEndpoint_thenEtagIsAlsoReturned() + throws Exception { + // Given + String createdResourceUri = this.mvc.perform(post(FOOS_ENDPOINT).contentType(MediaType.APPLICATION_JSON) + .content(createFooJson())) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader(HttpHeaders.LOCATION); + + // When + ResultActions result = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON)); + + // Then + result.andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.ETAG, "\"0\"")); + } + + @Test + public void givenResourceWasRetrieved_whenRetrievingAgainWithEtagUsingCustomEtagEndpoint_thenNotModifiedReturned() throws Exception { + // Given + String createdResourceUri = this.mvc.perform(post(FOOS_ENDPOINT).contentType(MediaType.APPLICATION_JSON) + .content(createFooJson())) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader(HttpHeaders.LOCATION); + ResultActions findOneResponse = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON)); + String etag = findOneResponse.andReturn().getResponse().getHeader(HttpHeaders.ETAG); + + // When + ResultActions result = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON).header(HttpHeaders.IF_NONE_MATCH, etag)); + + // Then + result.andExpect(status().isNotModified()); + } + + @Test + public void givenResourceWasRetrievedThenModified_whenRetrievingAgainWithEtagUsingCustomEtagEndpoint_thenResourceIsReturned() throws Exception { + // Given + String createdResourceUri = this.mvc.perform(post(FOOS_ENDPOINT).contentType(MediaType.APPLICATION_JSON) + .content(createFooJson())) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader(HttpHeaders.LOCATION); + ResultActions findOneResponse = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON)); + String etag = findOneResponse.andReturn().getResponse().getHeader(HttpHeaders.ETAG); + Foo createdFoo = deserializeFoo(findOneResponse.andReturn().getResponse().getContentAsString()); + createdFoo.setName("updated name"); + this.mvc + .perform(put(createdResourceUri).contentType(MediaType.APPLICATION_JSON).content(serializeFoo(createdFoo))); + + // When + ResultActions result = this.mvc + .perform(get(createdResourceUri + CUSTOM_ETAG_ENDPOINT_SUFFIX).contentType(MediaType.APPLICATION_JSON).header(HttpHeaders.IF_NONE_MATCH, etag)); + + // Then + result.andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.ETAG, "\"1\"")); + } + +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java index b7cceb9008..bc45d8352a 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/LiveTestSuiteLiveTest.java @@ -8,8 +8,8 @@ import org.junit.runners.Suite; @Suite.SuiteClasses({ // @formatter:off FooDiscoverabilityLiveTest.class, - FooLiveTest.class - ,FooPageableLiveTest.class + FooLiveTest.class, + FooPageableLiveTest.class }) // public class LiveTestSuiteLiveTest { diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index b8b9034a0b..32b65ccc6a 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -8,7 +8,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: -- [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) - [Integration Testing with the Maven Cargo plugin](http://www.baeldung.com/integration-testing-with-the-maven-cargo-plugin) - [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [Project Configuration with Spring](http://www.baeldung.com/project-configuration-with-spring) diff --git a/spring-rest-full/src/main/java/org/baeldung/spring/Application.java b/spring-rest-full/src/main/java/org/baeldung/spring/Application.java index 9a3f473b8b..950e2085a6 100644 --- a/spring-rest-full/src/main/java/org/baeldung/spring/Application.java +++ b/spring-rest-full/src/main/java/org/baeldung/spring/Application.java @@ -8,11 +8,9 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.context.request.RequestContextListener; -import org.springframework.web.filter.ShallowEtagHeaderFilter; /** * Main Application Class - uses Spring Boot. Just run this as a normal Java @@ -40,8 +38,4 @@ public class Application extends SpringBootServletInitializer { SpringApplication.run(Application.class, args); } - @Bean - public ShallowEtagHeaderFilter shallowEtagHeaderFilter() { - return new ShallowEtagHeaderFilter(); - } } \ No newline at end of file diff --git a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java index 9cb028bfdb..caaf422410 100644 --- a/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-rest-full/src/main/java/org/baeldung/web/controller/FooController.java @@ -6,10 +6,8 @@ import javax.servlet.http.HttpServletResponse; import org.baeldung.persistence.model.Foo; import org.baeldung.persistence.service.IFooService; -import org.baeldung.web.hateoas.event.ResourceCreatedEvent; import org.baeldung.web.util.RestPreconditions; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; @@ -26,9 +24,6 @@ import com.google.common.base.Preconditions; @RequestMapping(value = "/auth/foos") public class FooController { - @Autowired - private ApplicationEventPublisher eventPublisher; - @Autowired private IFooService service; @@ -71,9 +66,6 @@ public class FooController { public Foo create(@RequestBody final Foo resource, final HttpServletResponse response) { Preconditions.checkNotNull(resource); final Foo foo = service.create(resource); - final Long idOfCreatedResource = foo.getId(); - - eventPublisher.publishEvent(new ResourceCreatedEvent(this, response, idOfCreatedResource)); return foo; } diff --git a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/ResourceCreatedEvent.java b/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/ResourceCreatedEvent.java deleted file mode 100644 index efc04299bc..0000000000 --- a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/event/ResourceCreatedEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.baeldung.web.hateoas.event; - -import javax.servlet.http.HttpServletResponse; - -import org.springframework.context.ApplicationEvent; - -public class ResourceCreatedEvent extends ApplicationEvent { - private final HttpServletResponse response; - private final long idOfNewResource; - - public ResourceCreatedEvent(final Object source, final HttpServletResponse response, final long idOfNewResource) { - super(source); - - this.response = response; - this.idOfNewResource = idOfNewResource; - } - - // API - - public HttpServletResponse getResponse() { - return response; - } - - public long getIdOfNewResource() { - return idOfNewResource; - } - -} diff --git a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java b/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java deleted file mode 100644 index 0b308712cb..0000000000 --- a/spring-rest-full/src/main/java/org/baeldung/web/hateoas/listener/ResourceCreatedDiscoverabilityListener.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.baeldung.web.hateoas.listener; - -import java.net.URI; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.http.HttpHeaders; -import org.baeldung.web.hateoas.event.ResourceCreatedEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; - -import com.google.common.base.Preconditions; - -@Component -class ResourceCreatedDiscoverabilityListener implements ApplicationListener { - - @Override - public void onApplicationEvent(final ResourceCreatedEvent resourceCreatedEvent) { - Preconditions.checkNotNull(resourceCreatedEvent); - - final HttpServletResponse response = resourceCreatedEvent.getResponse(); - final long idOfNewResource = resourceCreatedEvent.getIdOfNewResource(); - - addLinkHeaderOnResourceCreation(response, idOfNewResource); - } - - void addLinkHeaderOnResourceCreation(final HttpServletResponse response, final long idOfNewResource) { - // final String requestUrl = request.getRequestURL().toString(); - // final URI uri = new UriTemplate("{requestUrl}/{idOfNewResource}").expand(requestUrl, idOfNewResource); - - final URI uri = ServletUriComponentsBuilder.fromCurrentRequestUri().path("/{idOfNewResource}").buildAndExpand(idOfNewResource).toUri(); - response.setHeader(HttpHeaders.LOCATION, uri.toASCIIString()); - } - -} \ No newline at end of file diff --git a/spring-rest-full/src/main/webapp/WEB-INF/web.xml b/spring-rest-full/src/main/webapp/WEB-INF/web.xml index 85bc72469e..5f90c3519f 100644 --- a/spring-rest-full/src/main/webapp/WEB-INF/web.xml +++ b/spring-rest-full/src/main/webapp/WEB-INF/web.xml @@ -23,15 +23,6 @@ org.springframework.web.context.ContextLoaderListener - - etagFilter - org.springframework.web.filter.ShallowEtagHeaderFilter - - - etagFilter - /* - - api diff --git a/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java deleted file mode 100644 index 76215bb6e3..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/TestSuiteLiveTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.baeldung; - -import org.baeldung.persistence.PersistenceTestSuite; -import org.baeldung.web.LiveTestSuiteLiveTest; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ -// @formatter:off - PersistenceTestSuite.class - ,LiveTestSuiteLiveTest.class -}) // -public class TestSuiteLiveTest { - -} diff --git a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java deleted file mode 100644 index d64807d97f..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractBasicLiveTest.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.baeldung.common.web; - -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.Serializable; - -import org.junit.Ignore; -import org.junit.Test; - -import com.google.common.net.HttpHeaders; - -import io.restassured.RestAssured; -import io.restassured.response.Response; - -public abstract class AbstractBasicLiveTest extends AbstractLiveTest { - - public AbstractBasicLiveTest(final Class clazzToSet) { - super(clazzToSet); - } - - // tests - - @Test - public void givenResourceExists_whenRetrievingResource_thenEtagIsAlsoReturned() { - // Given - final String uriOfResource = createAsUri(); - - // When - final Response findOneResponse = RestAssured.given() - .header("Accept", "application/json") - .get(uriOfResource); - - // Then - assertNotNull(findOneResponse.getHeader(HttpHeaders.ETAG)); - } - - @Test - public void givenResourceWasRetrieved_whenRetrievingAgainWithEtag_thenNotModifiedReturned() { - // Given - final String uriOfResource = createAsUri(); - final Response findOneResponse = RestAssured.given() - .header("Accept", "application/json") - .get(uriOfResource); - final String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG); - - // When - final Response secondFindOneResponse = RestAssured.given() - .header("Accept", "application/json") - .headers("If-None-Match", etagValue) - .get(uriOfResource); - - // Then - assertTrue(secondFindOneResponse.getStatusCode() == 304); - } - - @Test - @Ignore("No Update operation yet") - public void givenResourceWasRetrievedThenModified_whenRetrievingAgainWithEtag_thenResourceIsReturned() { - // Given - final String uriOfResource = createAsUri(); - final Response findOneResponse = RestAssured.given() - .header("Accept", "application/json") - .get(uriOfResource); - final String etagValue = findOneResponse.getHeader(HttpHeaders.ETAG); - - // existingResource.setName(randomAlphabetic(6)); - // getApi().update(existingResource.setName("randomString")); - - // When - final Response secondFindOneResponse = RestAssured.given() - .header("Accept", "application/json") - .headers("If-None-Match", etagValue) - .get(uriOfResource); - - // Then - assertTrue(secondFindOneResponse.getStatusCode() == 200); - } - - @Test - @Ignore("Not Yet Implemented By Spring - https://jira.springsource.org/browse/SPR-10164") - public void givenResourceExists_whenRetrievedWithIfMatchIncorrectEtag_then412IsReceived() { - // Given - final String uriOfResource = createAsUri(); - - // When - final Response findOneResponse = RestAssured.given() - .header("Accept", "application/json") - .headers("If-Match", randomAlphabetic(8)) - .get(uriOfResource); - - // Then - assertTrue(findOneResponse.getStatusCode() == 412); - } - - // find - one - - // find - all -} diff --git a/spring-rest-full/src/test/java/org/baeldung/web/FooLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/web/FooLiveTest.java deleted file mode 100644 index 65564a6845..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/web/FooLiveTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.baeldung.web; - -import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; - -import org.baeldung.common.web.AbstractBasicLiveTest; -import org.baeldung.persistence.model.Foo; -import org.baeldung.spring.ConfigIntegrationTest; -import org.junit.runner.RunWith; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { ConfigIntegrationTest.class }, loader = AnnotationConfigContextLoader.class) -@ActiveProfiles("test") -public class FooLiveTest extends AbstractBasicLiveTest { - - public FooLiveTest() { - super(Foo.class); - } - - // API - - @Override - public final void create() { - create(new Foo(randomAlphabetic(6))); - } - - @Override - public final String createAsUri() { - return createAsUri(new Foo(randomAlphabetic(6))); - } - -} diff --git a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java deleted file mode 100644 index 663935e72f..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/web/LiveTestSuiteLiveTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.baeldung.web; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ -// @formatter:off - FooLiveTest.class -}) // -public class LiveTestSuiteLiveTest { - -} From 1e9efcd606c678d4ad865c1b71131fd08ff8b6a0 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Sat, 23 Feb 2019 17:40:40 -0300 Subject: [PATCH 102/496] Added scenario using FooPageableLiveTest bean --- .../java/com/baeldung/spring/WebConfig.java | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index d5559bfae7..4b876a8338 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -2,6 +2,7 @@ package com.baeldung.spring; import java.util.List; +import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; @@ -35,26 +36,34 @@ public class WebConfig implements WebMvcConfigurer { // } // Another possibility is to create a bean which will be automatically added to the Spring Boot Autoconfigurations -// @Bean -// public HttpMessageConverter createXmlHttpMessageConverter() { -// final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); -// -// final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); -// xstreamMarshaller.setAutodetectAnnotations(true); -// xmlConverter.setMarshaller(xstreamMarshaller); -// xmlConverter.setUnmarshaller(xstreamMarshaller); -// -// return xmlConverter; -// } - - + // @Bean + // public HttpMessageConverter createXmlHttpMessageConverter() { + // final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); + // + // final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); + // xstreamMarshaller.setAutodetectAnnotations(true); + // xmlConverter.setMarshaller(xstreamMarshaller); + // xmlConverter.setUnmarshaller(xstreamMarshaller); + // + // return xmlConverter; + // } + // Etags - + // If we're not using Spring Boot we can make use of // AbstractAnnotationConfigDispatcherServletInitializer#getServletFilters @Bean - public ShallowEtagHeaderFilter shallowEtagHeaderFilter() { - return new ShallowEtagHeaderFilter(); + public FilterRegistrationBean shallowEtagHeaderFilter() { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>( new ShallowEtagHeaderFilter()); + filterRegistrationBean.addUrlPatterns("/auth/foos/*"); + filterRegistrationBean.setName("etagFilter"); + return filterRegistrationBean; } + + // We can also just declare the filter directly + // @Bean + // public ShallowEtagHeaderFilter shallowEtagHeaderFilter() { + // return new ShallowEtagHeaderFilter(); + // } } \ No newline at end of file From 7ee231b8171e73fce613b4fcd19d1441e34374c5 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Sun, 24 Feb 2019 11:49:28 -0300 Subject: [PATCH 103/496] [BAEL-11601] Move and update Testing REST with multiple MIME types article code Moved the code and cleaned spring-rest-full module. --- persistence-modules/spring-jpa/README.md | 1 - spring-boot-rest/README.md | 1 + .../baeldung/test/TestMarshallerFactory.java | 3 +- .../com}/baeldung/test/XStreamMarshaller.java | 4 +- spring-rest-full/pom.xml | 5 -- .../RestResponseEntityExceptionHandler.java | 25 ------ .../java/org/baeldung/web/util/LinkUtil.java | 36 --------- .../baeldung/common/web/AbstractLiveTest.java | 64 --------------- .../spring/ConfigIntegrationTest.java | 17 ---- .../java/org/baeldung/test/IMarshaller.java | 15 ---- .../org/baeldung/test/JacksonMarshaller.java | 81 ------------------- .../baeldung/test/TestMarshallerFactory.java | 48 ----------- 12 files changed, 4 insertions(+), 296 deletions(-) rename {spring-rest-full/src/test/java/org => spring-boot-rest/src/test/java/com}/baeldung/test/XStreamMarshaller.java (94%) delete mode 100644 spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java delete mode 100644 spring-rest-full/src/main/java/org/baeldung/web/util/LinkUtil.java delete mode 100644 spring-rest-full/src/test/java/org/baeldung/common/web/AbstractLiveTest.java delete mode 100644 spring-rest-full/src/test/java/org/baeldung/spring/ConfigIntegrationTest.java delete mode 100644 spring-rest-full/src/test/java/org/baeldung/test/IMarshaller.java delete mode 100644 spring-rest-full/src/test/java/org/baeldung/test/JacksonMarshaller.java delete mode 100644 spring-rest-full/src/test/java/org/baeldung/test/TestMarshallerFactory.java diff --git a/persistence-modules/spring-jpa/README.md b/persistence-modules/spring-jpa/README.md index 23c03d3bef..2f2a27e4ac 100644 --- a/persistence-modules/spring-jpa/README.md +++ b/persistence-modules/spring-jpa/README.md @@ -15,7 +15,6 @@ - [Self-Contained Testing Using an In-Memory Database](http://www.baeldung.com/spring-jpa-test-in-memory-database) - [A Guide to Spring AbstractRoutingDatasource](http://www.baeldung.com/spring-abstract-routing-data-source) - [A Guide to Hibernate with Spring 4](http://www.baeldung.com/the-persistence-layer-with-spring-and-jpa) -- [Testing REST with multiple MIME types](http://www.baeldung.com/testing-rest-api-with-multiple-media-types) - [Obtaining Auto-generated Keys in Spring JDBC](http://www.baeldung.com/spring-jdbc-autogenerated-keys) - [Transactions with Spring 4 and JPA](http://www.baeldung.com/transaction-configuration-with-jpa-and-spring) - [Use Criteria Queries in a Spring Data Application](https://www.baeldung.com/spring-data-criteria-queries) diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index a0adc5a51f..8fbc9527b8 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -9,3 +9,4 @@ Module for the articles that are part of the Spring REST E-book: 7. [Versioning a REST API](http://www.baeldung.com/rest-versioning) 8. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) 9. [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) +10. [Testing REST with multiple MIME types](http://www.baeldung.com/testing-rest-api-with-multiple-media-types) diff --git a/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java b/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java index 740ee07839..1a3bae7c87 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java +++ b/spring-boot-rest/src/test/java/com/baeldung/test/TestMarshallerFactory.java @@ -27,8 +27,7 @@ public class TestMarshallerFactory implements FactoryBean { case "json": return new JacksonMarshaller(); case "xml": - // If we need to implement xml marshaller we can include spring-rest-full XStreamMarshaller - throw new IllegalStateException(); + return new XStreamMarshaller(); default: throw new IllegalStateException(); } diff --git a/spring-rest-full/src/test/java/org/baeldung/test/XStreamMarshaller.java b/spring-boot-rest/src/test/java/com/baeldung/test/XStreamMarshaller.java similarity index 94% rename from spring-rest-full/src/test/java/org/baeldung/test/XStreamMarshaller.java rename to spring-boot-rest/src/test/java/com/baeldung/test/XStreamMarshaller.java index d7cf084e34..957b35218e 100644 --- a/spring-rest-full/src/test/java/org/baeldung/test/XStreamMarshaller.java +++ b/spring-boot-rest/src/test/java/com/baeldung/test/XStreamMarshaller.java @@ -1,8 +1,8 @@ -package org.baeldung.test; +package com.baeldung.test; import java.util.List; -import org.baeldung.persistence.model.Foo; +import com.baeldung.persistence.model.Foo; import org.springframework.http.MediaType; import com.google.common.base.Preconditions; diff --git a/spring-rest-full/pom.xml b/spring-rest-full/pom.xml index ddc7e042b5..ee6e5dbe3e 100644 --- a/spring-rest-full/pom.xml +++ b/spring-rest-full/pom.xml @@ -158,11 +158,6 @@ com.fasterxml.jackson.core jackson-databind - - com.thoughtworks.xstream - xstream - ${xstream.version} - diff --git a/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java deleted file mode 100644 index c0639acef4..0000000000 --- a/spring-rest-full/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.baeldung.web.error; - -import org.baeldung.web.exception.MyResourceNotFoundException; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.context.request.WebRequest; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; - -@ControllerAdvice -public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { - - public RestResponseEntityExceptionHandler() { - super(); - } - - @ExceptionHandler(value = { MyResourceNotFoundException.class }) - protected ResponseEntity handleNotFound(final RuntimeException ex, final WebRequest request) { - final String bodyOfResponse = "This should be application specific"; - return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request); - } - -} diff --git a/spring-rest-full/src/main/java/org/baeldung/web/util/LinkUtil.java b/spring-rest-full/src/main/java/org/baeldung/web/util/LinkUtil.java deleted file mode 100644 index b2137aeeff..0000000000 --- a/spring-rest-full/src/main/java/org/baeldung/web/util/LinkUtil.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.baeldung.web.util; - -import javax.servlet.http.HttpServletResponse; - -/** - * Provides some constants and utility methods to build a Link Header to be stored in the {@link HttpServletResponse} object - */ -public final class LinkUtil { - - public static final String REL_COLLECTION = "collection"; - public static final String REL_NEXT = "next"; - public static final String REL_PREV = "prev"; - public static final String REL_FIRST = "first"; - public static final String REL_LAST = "last"; - - private LinkUtil() { - throw new AssertionError(); - } - - // - - /** - * Creates a Link Header to be stored in the {@link HttpServletResponse} to provide Discoverability features to the user - * - * @param uri - * the base uri - * @param rel - * the relative path - * - * @return the complete url - */ - public static String createLinkHeader(final String uri, final String rel) { - return "<" + uri + ">; rel=\"" + rel + "\""; - } - -} diff --git a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractLiveTest.java b/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractLiveTest.java deleted file mode 100644 index 5aa0f5a768..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/common/web/AbstractLiveTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.baeldung.common.web; - -import static org.baeldung.Consts.APPLICATION_PORT; -import io.restassured.RestAssured; -import io.restassured.response.Response; - -import java.io.Serializable; - -import org.baeldung.test.IMarshaller; -import org.springframework.beans.factory.annotation.Autowired; - -import com.google.common.base.Preconditions; -import com.google.common.net.HttpHeaders; - -public abstract class AbstractLiveTest { - - protected final Class clazz; - - @Autowired - protected IMarshaller marshaller; - - public AbstractLiveTest(final Class clazzToSet) { - super(); - - Preconditions.checkNotNull(clazzToSet); - clazz = clazzToSet; - } - - // template method - - public abstract void create(); - - public abstract String createAsUri(); - - protected final void create(final T resource) { - createAsUri(resource); - } - - protected final String createAsUri(final T resource) { - final Response response = createAsResponse(resource); - Preconditions.checkState(response.getStatusCode() == 201, "create operation: " + response.getStatusCode()); - - final String locationOfCreatedResource = response.getHeader(HttpHeaders.LOCATION); - Preconditions.checkNotNull(locationOfCreatedResource); - return locationOfCreatedResource; - } - - final Response createAsResponse(final T resource) { - Preconditions.checkNotNull(resource); - - final String resourceAsString = marshaller.encode(resource); - return RestAssured.given() - .contentType(marshaller.getMime()) - .body(resourceAsString) - .post(getURL()); - } - - // - - protected String getURL() { - return "http://localhost:" + APPLICATION_PORT + "/spring-rest-full/auth/foos"; - } - -} diff --git a/spring-rest-full/src/test/java/org/baeldung/spring/ConfigIntegrationTest.java b/spring-rest-full/src/test/java/org/baeldung/spring/ConfigIntegrationTest.java deleted file mode 100644 index 77603da0dd..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/spring/ConfigIntegrationTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.baeldung.spring; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - -@Configuration -@ComponentScan("org.baeldung.test") -public class ConfigIntegrationTest extends WebMvcConfigurerAdapter { - - public ConfigIntegrationTest() { - super(); - } - - // API - -} \ No newline at end of file diff --git a/spring-rest-full/src/test/java/org/baeldung/test/IMarshaller.java b/spring-rest-full/src/test/java/org/baeldung/test/IMarshaller.java deleted file mode 100644 index 1eefbe8789..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/test/IMarshaller.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.baeldung.test; - -import java.util.List; - -public interface IMarshaller { - - String encode(final T entity); - - T decode(final String entityAsString, final Class clazz); - - List decodeList(final String entitiesAsString, final Class clazz); - - String getMime(); - -} diff --git a/spring-rest-full/src/test/java/org/baeldung/test/JacksonMarshaller.java b/spring-rest-full/src/test/java/org/baeldung/test/JacksonMarshaller.java deleted file mode 100644 index 912ad89ed7..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/test/JacksonMarshaller.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.baeldung.test; - -import java.io.IOException; -import java.util.List; - -import org.baeldung.persistence.model.Foo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.MediaType; - -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Preconditions; - -public final class JacksonMarshaller implements IMarshaller { - private final Logger logger = LoggerFactory.getLogger(JacksonMarshaller.class); - - private final ObjectMapper objectMapper; - - public JacksonMarshaller() { - super(); - - objectMapper = new ObjectMapper(); - } - - // API - - @Override - public final String encode(final T resource) { - Preconditions.checkNotNull(resource); - String entityAsJSON = null; - try { - entityAsJSON = objectMapper.writeValueAsString(resource); - } catch (final IOException ioEx) { - logger.error("", ioEx); - } - - return entityAsJSON; - } - - @Override - public final T decode(final String resourceAsString, final Class clazz) { - Preconditions.checkNotNull(resourceAsString); - - T entity = null; - try { - entity = objectMapper.readValue(resourceAsString, clazz); - } catch (final IOException ioEx) { - logger.error("", ioEx); - } - - return entity; - } - - @SuppressWarnings("unchecked") - @Override - public final List decodeList(final String resourcesAsString, final Class clazz) { - Preconditions.checkNotNull(resourcesAsString); - - List entities = null; - try { - if (clazz.equals(Foo.class)) { - entities = objectMapper.readValue(resourcesAsString, new TypeReference>() { - // ... - }); - } else { - entities = objectMapper.readValue(resourcesAsString, List.class); - } - } catch (final IOException ioEx) { - logger.error("", ioEx); - } - - return entities; - } - - @Override - public final String getMime() { - return MediaType.APPLICATION_JSON.toString(); - } - -} diff --git a/spring-rest-full/src/test/java/org/baeldung/test/TestMarshallerFactory.java b/spring-rest-full/src/test/java/org/baeldung/test/TestMarshallerFactory.java deleted file mode 100644 index 11273276cd..0000000000 --- a/spring-rest-full/src/test/java/org/baeldung/test/TestMarshallerFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.baeldung.test; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Profile; -import org.springframework.core.env.Environment; -import org.springframework.stereotype.Component; - -@Component -@Profile("test") -public class TestMarshallerFactory implements FactoryBean { - - @Autowired - private Environment env; - - public TestMarshallerFactory() { - super(); - } - - // API - - @Override - public IMarshaller getObject() { - final String testMime = env.getProperty("test.mime"); - if (testMime != null) { - switch (testMime) { - case "json": - return new JacksonMarshaller(); - case "xml": - return new XStreamMarshaller(); - default: - throw new IllegalStateException(); - } - } - - return new JacksonMarshaller(); - } - - @Override - public Class getObjectType() { - return IMarshaller.class; - } - - @Override - public boolean isSingleton() { - return true; - } -} \ No newline at end of file From b48e5648144a5bb943b503b65bb3a0ff1a28402e Mon Sep 17 00:00:00 2001 From: Doha2012 Date: Sun, 24 Feb 2019 19:03:09 +0200 Subject: [PATCH 104/496] keycloak - change server port (#6401) * add user-info endpoint live test * keycloak - change server port --- spring-boot-keycloak/src/main/resources/application.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/spring-boot-keycloak/src/main/resources/application.properties b/spring-boot-keycloak/src/main/resources/application.properties index f667d3b27e..6e7da2cb90 100644 --- a/spring-boot-keycloak/src/main/resources/application.properties +++ b/spring-boot-keycloak/src/main/resources/application.properties @@ -1,3 +1,6 @@ +### server port +server.port=8081 + #Keycloak Configuration keycloak.auth-server-url=http://localhost:8180/auth keycloak.realm=SpringBootKeycloak From c0b4579093e30d0d186786416a54b45bfd1be8e4 Mon Sep 17 00:00:00 2001 From: fanatixan Date: Sun, 24 Feb 2019 18:09:22 +0100 Subject: [PATCH 105/496] bael-2383: memory polluting code for testing epsilon gc (#6403) --- .../com/baeldung/epsilongc/MemoryPolluter.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 core-java-11/src/main/java/com/baeldung/epsilongc/MemoryPolluter.java diff --git a/core-java-11/src/main/java/com/baeldung/epsilongc/MemoryPolluter.java b/core-java-11/src/main/java/com/baeldung/epsilongc/MemoryPolluter.java new file mode 100644 index 0000000000..97e216513b --- /dev/null +++ b/core-java-11/src/main/java/com/baeldung/epsilongc/MemoryPolluter.java @@ -0,0 +1,18 @@ +package com.baeldung.epsilongc; + +public class MemoryPolluter { + + private static final int MEGABYTE_IN_BYTES = 1024 * 1024; + private static final int ITERATION_COUNT = 1024 * 10; + + public static void main(String[] args) { + System.out.println("Starting pollution"); + + for (int i = 0; i < ITERATION_COUNT; i++) { + byte[] array = new byte[MEGABYTE_IN_BYTES]; + } + + System.out.println("Terminating"); + } + +} From ae575b50456e027870642ec6bf5fb7131e2c75a4 Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 24 Feb 2019 19:26:57 +0200 Subject: [PATCH 106/496] fix smooks test, add libraries to main pom integration profile --- .../smooks/converter/SmooksIntegrationTest.java | 12 ++++++++---- pom.xml | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libraries/src/test/java/com/baeldung/smooks/converter/SmooksIntegrationTest.java b/libraries/src/test/java/com/baeldung/smooks/converter/SmooksIntegrationTest.java index 69af042427..df7fea58f8 100644 --- a/libraries/src/test/java/com/baeldung/smooks/converter/SmooksIntegrationTest.java +++ b/libraries/src/test/java/com/baeldung/smooks/converter/SmooksIntegrationTest.java @@ -12,9 +12,10 @@ import static org.junit.Assert.*; public class SmooksIntegrationTest { - private static final String EDIFACT_MESSAGE = "UNA:+.? '\r\n" + "UNH+771+IN_PROGRESS+2018-01-14'\r\n" + "CTA+CompanyX+1234567'\r\n" + "LIN+1+PX1234+9.99'\r\n" + "LIN+2+RX990+120.32'\r\n"; - private static final String EMAIL_MESSAGE = "Hi,\r\n" + "Order number #771 created on 2018-01-14 is currently in IN_PROGRESS status.\r\n" + "Consider contact supplier \"CompanyX\" with phone number: \"1234567\".\r\n" + "Order items:\r\n" - + "1 X PX1234 (total price 9.99)\r\n" + "2 X RX990 (total price 240.64)\r\n"; + private static final String EDIFACT_MESSAGE = "UNA:+.? '" + System.lineSeparator() + "UNH+771+IN_PROGRESS+2018-01-14'" + System.lineSeparator() + "CTA+CompanyX+1234567'" + System.lineSeparator() + "LIN+1+PX1234+9.99'" + System.lineSeparator() + + "LIN+2+RX990+120.32'" + System.lineSeparator(); + private static final String EMAIL_MESSAGE = "Hi," + System.lineSeparator() + "Order number #771 created on 2018-01-14 is currently in IN_PROGRESS status." + System.lineSeparator() + "Consider contact supplier \"CompanyX\" with phone number: \"1234567\"." + + System.lineSeparator() + "Order items:" + System.lineSeparator() + "1 X PX1234 (total price 9.99)" + System.lineSeparator() + "2 X RX990 (total price 240.64)" + System.lineSeparator(); @Test public void givenOrderXML_whenConvert_thenPOJOsConstructedCorrectly() throws Exception { @@ -37,7 +38,10 @@ public class SmooksIntegrationTest { assertThat(validationResult.getErrors(), hasSize(1)); // 1234567 didn't match ^[0-9\\-\\+]{9,15}$ - assertThat(validationResult.getErrors().get(0).getFailRuleResult().getRuleName(), is("supplierPhone")); + assertThat(validationResult.getErrors() + .get(0) + .getFailRuleResult() + .getRuleName(), is("supplierPhone")); } @Test diff --git a/pom.xml b/pom.xml index 4d4cd574d7..ebebb62344 100644 --- a/pom.xml +++ b/pom.xml @@ -1194,6 +1194,7 @@ kotlin-libraries + libraries libraries-data libraries-apache-commons libraries-security From 8bb49f78eb2b239e393bc526ba01c36700769db3 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 24 Feb 2019 20:03:02 +0200 Subject: [PATCH 107/496] Update README.md --- patterns/design-patterns/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/patterns/design-patterns/README.md b/patterns/design-patterns/README.md index 8046d2034b..a4513b7d95 100644 --- a/patterns/design-patterns/README.md +++ b/patterns/design-patterns/README.md @@ -18,3 +18,4 @@ - [Chain of Responsibility Design Pattern in Java](http://www.baeldung.com/chain-of-responsibility-pattern) - [The Command Pattern in Java](http://www.baeldung.com/java-command-pattern) - [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods) +- [The Adapter Pattern in Java](https://www.baeldung.com/java-adapter-pattern) From 276e37dc6e3b55666fe32fdb81a7ab007d229d04 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 24 Feb 2019 23:34:48 +0530 Subject: [PATCH 108/496] [BAEL-9695] - Upgraded parent-spring-4 to the latest version of Spring 4 : 4.3.22 --- parent-spring-4/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parent-spring-4/pom.xml b/parent-spring-4/pom.xml index 6cbcf3000e..d7eea44989 100644 --- a/parent-spring-4/pom.xml +++ b/parent-spring-4/pom.xml @@ -29,7 +29,7 @@ - 4.3.20.RELEASE + 4.3.22.RELEASE 5.0.2 From 10782a2db8596e1c616159625c90841d236d66af Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 24 Feb 2019 23:56:14 +0530 Subject: [PATCH 109/496] [BAEL-9638] - Upgrade parent-boot-2 to the latest version of Boot 2.x : 2.1.3 --- parent-boot-2/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml index 280d226e95..449731150b 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -77,8 +77,8 @@ 3.1.0 - 1.0.11.RELEASE - 2.1.1.RELEASE + 1.0.21.RELEASE + 2.1.3.RELEASE From e4f65cbadc5546ad5d8808704eed7f3374428810 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Mon, 25 Feb 2019 17:58:21 +0530 Subject: [PATCH 110/496] BAEL-10959 All tests were connecting to live couchbase instance, hence renamed to *LiveTest --- ...ContextIntegrationTest.java => SpringContextLiveTest.java} | 2 +- ...egrationTest.java => PersonRepositoryServiceLiveTest.java} | 2 +- ...ServiceIntegrationTest.java => PersonServiceLiveTest.java} | 2 +- ...ntegrationTest.java => PersonTemplateServiceLiveTest.java} | 2 +- ...grationTest.java => StudentRepositoryServiceLiveTest.java} | 2 +- ...erviceIntegrationTest.java => StudentServiceLiveTest.java} | 2 +- ...tegrationTest.java => StudentTemplateServiceLiveTest.java} | 2 +- ...ltiBucketIntegrationTest.java => MultiBucketLiveTest.java} | 2 +- ...mplIntegrationTest.java => CampusServiceImplLiveTest.java} | 4 ++-- ...mplIntegrationTest.java => PersonServiceImplLiveTest.java} | 4 ++-- ...plIntegrationTest.java => StudentServiceImplLiveTest.java} | 4 ++-- 11 files changed, 14 insertions(+), 14 deletions(-) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/{SpringContextIntegrationTest.java => SpringContextLiveTest.java} (95%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/{PersonRepositoryServiceIntegrationTest.java => PersonRepositoryServiceLiveTest.java} (78%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/{PersonServiceIntegrationTest.java => PersonServiceLiveTest.java} (98%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/{PersonTemplateServiceIntegrationTest.java => PersonTemplateServiceLiveTest.java} (79%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/{StudentRepositoryServiceIntegrationTest.java => StudentRepositoryServiceLiveTest.java} (78%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/{StudentServiceIntegrationTest.java => StudentServiceLiveTest.java} (98%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/{StudentTemplateServiceIntegrationTest.java => StudentTemplateServiceLiveTest.java} (79%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/{MultiBucketIntegrationTest.java => MultiBucketLiveTest.java} (92%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/{CampusServiceImplIntegrationTest.java => CampusServiceImplLiveTest.java} (96%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/{PersonServiceImplIntegrationTest.java => PersonServiceImplLiveTest.java} (96%) rename persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/{StudentServiceImplIntegrationTest.java => StudentServiceImplLiveTest.java} (97%) diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextLiveTest.java similarity index 95% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextLiveTest.java index 9c9d58dd0b..af228735b8 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextLiveTest.java @@ -12,7 +12,7 @@ import org.springframework.test.context.support.DependencyInjectionTestExecution @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { MultiBucketCouchbaseConfig.class, MultiBucketIntegrationTestConfig.class }) @TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) -public class SpringContextIntegrationTest { +public class SpringContextLiveTest { @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceLiveTest.java similarity index 78% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceLiveTest.java index d710e57def..899c21691d 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonRepositoryServiceLiveTest.java @@ -3,7 +3,7 @@ package org.baeldung.spring.data.couchbase.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -public class PersonRepositoryServiceIntegrationTest extends PersonServiceIntegrationTest { +public class PersonRepositoryServiceLiveTest extends PersonServiceLiveTest { @Autowired @Qualifier("PersonRepositoryService") diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonServiceIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonServiceLiveTest.java similarity index 98% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonServiceIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonServiceLiveTest.java index 4044183849..08d641dc2c 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonServiceIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonServiceLiveTest.java @@ -20,7 +20,7 @@ import com.couchbase.client.java.CouchbaseCluster; import com.couchbase.client.java.document.JsonDocument; import com.couchbase.client.java.document.json.JsonObject; -public abstract class PersonServiceIntegrationTest extends IntegrationTest { +public abstract class PersonServiceLiveTest extends IntegrationTest { static final String typeField = "_class"; static final String john = "John"; diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonTemplateServiceIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonTemplateServiceLiveTest.java similarity index 79% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonTemplateServiceIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonTemplateServiceLiveTest.java index e19df8fc84..3bc99d28df 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonTemplateServiceIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/PersonTemplateServiceLiveTest.java @@ -3,7 +3,7 @@ package org.baeldung.spring.data.couchbase.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -public class PersonTemplateServiceIntegrationTest extends PersonServiceIntegrationTest { +public class PersonTemplateServiceLiveTest extends PersonServiceLiveTest { @Autowired @Qualifier("PersonTemplateService") diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceLiveTest.java similarity index 78% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceLiveTest.java index 3b3f2a531a..162619db3e 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentRepositoryServiceLiveTest.java @@ -3,7 +3,7 @@ package org.baeldung.spring.data.couchbase.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -public class StudentRepositoryServiceIntegrationTest extends StudentServiceIntegrationTest { +public class StudentRepositoryServiceLiveTest extends StudentServiceLiveTest { @Autowired @Qualifier("StudentRepositoryService") diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentServiceIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentServiceLiveTest.java similarity index 98% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentServiceIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentServiceLiveTest.java index fba549a9e5..6a18922007 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentServiceIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentServiceLiveTest.java @@ -22,7 +22,7 @@ import com.couchbase.client.java.CouchbaseCluster; import com.couchbase.client.java.document.JsonDocument; import com.couchbase.client.java.document.json.JsonObject; -public abstract class StudentServiceIntegrationTest extends IntegrationTest { +public abstract class StudentServiceLiveTest extends IntegrationTest { static final String typeField = "_class"; static final String joe = "Joe"; diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentTemplateServiceIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentTemplateServiceLiveTest.java similarity index 79% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentTemplateServiceIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentTemplateServiceLiveTest.java index 29fd605bc6..c666e004af 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentTemplateServiceIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase/service/StudentTemplateServiceLiveTest.java @@ -3,7 +3,7 @@ package org.baeldung.spring.data.couchbase.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; -public class StudentTemplateServiceIntegrationTest extends StudentServiceIntegrationTest { +public class StudentTemplateServiceLiveTest extends StudentServiceLiveTest { @Autowired @Qualifier("StudentTemplateService") diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketLiveTest.java similarity index 92% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketLiveTest.java index 05ba58d616..3b406a851e 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/MultiBucketLiveTest.java @@ -9,6 +9,6 @@ import org.springframework.test.context.support.DependencyInjectionTestExecution @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { MultiBucketCouchbaseConfig.class, MultiBucketIntegrationTestConfig.class }) @TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) -public abstract class MultiBucketIntegrationTest { +public abstract class MultiBucketLiveTest { } diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImplIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImplLiveTest.java similarity index 96% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImplIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImplLiveTest.java index 0996b252f1..5e7a12f292 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImplIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/CampusServiceImplLiveTest.java @@ -10,7 +10,7 @@ import java.util.Set; import javax.annotation.PostConstruct; import org.baeldung.spring.data.couchbase.model.Campus; -import org.baeldung.spring.data.couchbase2b.MultiBucketIntegrationTest; +import org.baeldung.spring.data.couchbase2b.MultiBucketLiveTest; import org.baeldung.spring.data.couchbase2b.repos.CampusRepository; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -18,7 +18,7 @@ import org.springframework.data.geo.Distance; import org.springframework.data.geo.Metrics; import org.springframework.data.geo.Point; -public class CampusServiceImplIntegrationTest extends MultiBucketIntegrationTest { +public class CampusServiceImplLiveTest extends MultiBucketLiveTest { @Autowired private CampusServiceImpl campusService; diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImplIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImplLiveTest.java similarity index 96% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImplIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImplLiveTest.java index 45475e50f6..9543d8fe12 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImplIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/PersonServiceImplLiveTest.java @@ -9,7 +9,7 @@ import java.util.List; import org.baeldung.spring.data.couchbase.model.Person; import org.baeldung.spring.data.couchbase2b.MultiBucketCouchbaseConfig; -import org.baeldung.spring.data.couchbase2b.MultiBucketIntegrationTest; +import org.baeldung.spring.data.couchbase2b.MultiBucketLiveTest; import org.joda.time.DateTime; import org.junit.BeforeClass; import org.junit.Test; @@ -21,7 +21,7 @@ import com.couchbase.client.java.CouchbaseCluster; import com.couchbase.client.java.document.JsonDocument; import com.couchbase.client.java.document.json.JsonObject; -public class PersonServiceImplIntegrationTest extends MultiBucketIntegrationTest { +public class PersonServiceImplLiveTest extends MultiBucketLiveTest { static final String typeField = "_class"; static final String john = "John"; diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImplIntegrationTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImplLiveTest.java similarity index 97% rename from persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImplIntegrationTest.java rename to persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImplLiveTest.java index e7c1eab92a..52b9113e8f 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImplIntegrationTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/spring/data/couchbase2b/service/StudentServiceImplLiveTest.java @@ -11,7 +11,7 @@ import javax.validation.ConstraintViolationException; import org.baeldung.spring.data.couchbase.model.Student; import org.baeldung.spring.data.couchbase2b.MultiBucketCouchbaseConfig; -import org.baeldung.spring.data.couchbase2b.MultiBucketIntegrationTest; +import org.baeldung.spring.data.couchbase2b.MultiBucketLiveTest; import org.joda.time.DateTime; import org.junit.BeforeClass; import org.junit.Test; @@ -23,7 +23,7 @@ import com.couchbase.client.java.CouchbaseCluster; import com.couchbase.client.java.document.JsonDocument; import com.couchbase.client.java.document.json.JsonObject; -public class StudentServiceImplIntegrationTest extends MultiBucketIntegrationTest { +public class StudentServiceImplLiveTest extends MultiBucketLiveTest { static final String typeField = "_class"; static final String joe = "Joe"; From 053e7c4e98d063e9921cffeda473642e3058cd74 Mon Sep 17 00:00:00 2001 From: the-java-guy <39062630+the-java-guy@users.noreply.github.com> Date: Mon, 25 Feb 2019 22:25:25 +0530 Subject: [PATCH 111/496] BAEL-774 (#6234) * BAEL-774 * BAEL 774 : Refactored methods * BAEL-774 Refactored to new module. * BAEL 774 - CRs * BAEL 774 - Moved code back to ratpack module * Removed modules reactive-modules and ratpack-rxjava * Refactored packages --- pom.xml | 1 - .../main/java/com/baeldung/model/Movie.java | 47 +++++++++++++++++++ .../rxjava/RatpackErrorHandlingApp.java | 27 +++++++++++ .../baeldung/rxjava/RatpackObserveApp.java | 44 +++++++++++++++++ .../rxjava/RatpackParallelismApp.java | 36 ++++++++++++++ .../baeldung/rxjava/RatpackPromiseApp.java | 43 +++++++++++++++++ .../service/MovieObservableService.java | 13 +++++ .../rxjava/service/MoviePromiseService.java | 15 ++++++ .../impl/MovieObservableServiceImpl.java | 35 ++++++++++++++ .../service/impl/MoviePromiseServiceImpl.java | 41 ++++++++++++++++ 10 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 ratpack/src/main/java/com/baeldung/model/Movie.java create mode 100644 ratpack/src/main/java/com/baeldung/rxjava/RatpackErrorHandlingApp.java create mode 100644 ratpack/src/main/java/com/baeldung/rxjava/RatpackObserveApp.java create mode 100644 ratpack/src/main/java/com/baeldung/rxjava/RatpackParallelismApp.java create mode 100644 ratpack/src/main/java/com/baeldung/rxjava/RatpackPromiseApp.java create mode 100644 ratpack/src/main/java/com/baeldung/rxjava/service/MovieObservableService.java create mode 100644 ratpack/src/main/java/com/baeldung/rxjava/service/MoviePromiseService.java create mode 100644 ratpack/src/main/java/com/baeldung/rxjava/service/impl/MovieObservableServiceImpl.java create mode 100644 ratpack/src/main/java/com/baeldung/rxjava/service/impl/MoviePromiseServiceImpl.java diff --git a/pom.xml b/pom.xml index 9b36b30f59..4625f8e6e8 100644 --- a/pom.xml +++ b/pom.xml @@ -570,7 +570,6 @@ rxjava rxjava-2 software-security/sql-injection-samples - diff --git a/ratpack/src/main/java/com/baeldung/model/Movie.java b/ratpack/src/main/java/com/baeldung/model/Movie.java new file mode 100644 index 0000000000..6618e9bbb7 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/model/Movie.java @@ -0,0 +1,47 @@ +package com.baeldung.model; +/** + * + *POJO class for Movie object + */ +public class Movie { + + private String name; + + private String year; + + private String director; + + private Double rating; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getYear() { + return year; + } + + public void setYear(String year) { + this.year = year; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public Double getRating() { + return rating; + } + + public void setRating(Double rating) { + this.rating = rating; + } +} diff --git a/ratpack/src/main/java/com/baeldung/rxjava/RatpackErrorHandlingApp.java b/ratpack/src/main/java/com/baeldung/rxjava/RatpackErrorHandlingApp.java new file mode 100644 index 0000000000..7d2eba56fb --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/rxjava/RatpackErrorHandlingApp.java @@ -0,0 +1,27 @@ +package com.baeldung.rxjava; + +import ratpack.error.ServerErrorHandler; +import ratpack.rx.RxRatpack; +import ratpack.server.RatpackServer; +import rx.Observable; + +public class RatpackErrorHandlingApp { + + /** + * Try hitting http://localhost:5050/error to see the error handler in action + * @param args + * @throws Exception + */ + + public static void main(String[] args) throws Exception { + RxRatpack.initialize(); + RatpackServer.start(def -> def.registryOf(regSpec -> regSpec.add(ServerErrorHandler.class, (ctx, throwable) -> { + ctx.render("Error caught by handler : " + throwable.getMessage()); + })) + .handlers(chain -> chain.get("error", ctx -> { + Observable. error(new Exception("Error from observable")) + .subscribe(s -> { + }); + }))); + } +} diff --git a/ratpack/src/main/java/com/baeldung/rxjava/RatpackObserveApp.java b/ratpack/src/main/java/com/baeldung/rxjava/RatpackObserveApp.java new file mode 100644 index 0000000000..d5ef105207 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/rxjava/RatpackObserveApp.java @@ -0,0 +1,44 @@ +package com.baeldung.rxjava; + +import java.util.List; + +import com.baeldung.model.Movie; +import com.baeldung.rxjava.service.MoviePromiseService; +import com.baeldung.rxjava.service.impl.MoviePromiseServiceImpl; + +import ratpack.exec.Promise; +import ratpack.handling.Handler; +import ratpack.jackson.Jackson; +import ratpack.rx.RxRatpack; +import ratpack.server.RatpackServer; + +public class RatpackObserveApp { + /** + * Try hitting http://localhost:5050/movies or http://localhost:5050/movie to see the application in action. + * + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + RxRatpack.initialize(); + + Handler moviePromiseHandler = ctx -> { + MoviePromiseService promiseSvc = ctx.get(MoviePromiseService.class); + Promise moviePromise = promiseSvc.getMovie(); + RxRatpack.observe(moviePromise) + .subscribe(movie -> ctx.render(Jackson.json(movie))); + }; + + Handler moviesPromiseHandler = ctx -> { + MoviePromiseService promiseSvc = ctx.get(MoviePromiseService.class); + Promise> moviePromises = promiseSvc.getMovies(); + RxRatpack.observeEach(moviePromises) + .toList() + .subscribe(movie -> ctx.render(Jackson.json(movie))); + }; + + RatpackServer.start(def -> def.registryOf(regSpec -> regSpec.add(MoviePromiseService.class, new MoviePromiseServiceImpl())) + .handlers(chain -> chain.get("movie", moviePromiseHandler) + .get("movies", moviesPromiseHandler))); + } +} diff --git a/ratpack/src/main/java/com/baeldung/rxjava/RatpackParallelismApp.java b/ratpack/src/main/java/com/baeldung/rxjava/RatpackParallelismApp.java new file mode 100644 index 0000000000..033c3e73b5 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/rxjava/RatpackParallelismApp.java @@ -0,0 +1,36 @@ +package com.baeldung.rxjava; + +import com.baeldung.model.Movie; +import com.baeldung.rxjava.service.MovieObservableService; +import com.baeldung.rxjava.service.impl.MovieObservableServiceImpl; + +import ratpack.jackson.Jackson; +import ratpack.rx.RxRatpack; +import ratpack.server.RatpackServer; +import rx.Observable; + +public class RatpackParallelismApp { + + /** + * Try hitting http://localhost:5050/movies to see the application in action. + * + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + RxRatpack.initialize(); + RatpackServer.start(def -> def.registryOf(regSpec -> regSpec.add(MovieObservableService.class, new MovieObservableServiceImpl())) + .handlers(chain -> chain.get("movies", ctx -> { + MovieObservableService movieSvc = ctx.get(MovieObservableService.class); + Observable movieObs = movieSvc.getMovies(); + Observable upperCasedNames = movieObs.compose(RxRatpack::forkEach) + .map(movie -> movie.getName() + .toUpperCase()) + .serialize(); + RxRatpack.promise(upperCasedNames) + .then(movie -> { + ctx.render(Jackson.json(movie)); + }); + }))); + } +} diff --git a/ratpack/src/main/java/com/baeldung/rxjava/RatpackPromiseApp.java b/ratpack/src/main/java/com/baeldung/rxjava/RatpackPromiseApp.java new file mode 100644 index 0000000000..8a9c00b788 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/rxjava/RatpackPromiseApp.java @@ -0,0 +1,43 @@ +package com.baeldung.rxjava; + +import com.baeldung.model.Movie; +import com.baeldung.rxjava.service.MovieObservableService; +import com.baeldung.rxjava.service.impl.MovieObservableServiceImpl; + +import ratpack.handling.Handler; +import ratpack.jackson.Jackson; +import ratpack.rx.RxRatpack; +import ratpack.server.RatpackServer; +import rx.Observable; + +public class RatpackPromiseApp { + + /** + * Try hitting http://localhost:5050/movies or http://localhost:5050/movie to see the application in action. + * + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + RxRatpack.initialize(); + + Handler movieHandler = (ctx) -> { + MovieObservableService movieSvc = ctx.get(MovieObservableService.class); + Observable movieObs = movieSvc.getMovie(); + RxRatpack.promiseSingle(movieObs) + .then(movie -> ctx.render(Jackson.json(movie))); + }; + + Handler moviesHandler = (ctx) -> { + MovieObservableService movieSvc = ctx.get(MovieObservableService.class); + Observable movieObs = movieSvc.getMovies(); + RxRatpack.promise(movieObs) + .then(movie -> ctx.render(Jackson.json(movie))); + }; + + RatpackServer.start(def -> def.registryOf(rSpec -> rSpec.add(MovieObservableService.class, new MovieObservableServiceImpl())) + .handlers(chain -> chain.get("movie", movieHandler) + .get("movies", moviesHandler))); + } + +} diff --git a/ratpack/src/main/java/com/baeldung/rxjava/service/MovieObservableService.java b/ratpack/src/main/java/com/baeldung/rxjava/service/MovieObservableService.java new file mode 100644 index 0000000000..75a90faa44 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/rxjava/service/MovieObservableService.java @@ -0,0 +1,13 @@ +package com.baeldung.rxjava.service; + +import com.baeldung.model.Movie; + +import rx.Observable; + +public interface MovieObservableService { + + Observable getMovies(); + + Observable getMovie(); + +} diff --git a/ratpack/src/main/java/com/baeldung/rxjava/service/MoviePromiseService.java b/ratpack/src/main/java/com/baeldung/rxjava/service/MoviePromiseService.java new file mode 100644 index 0000000000..fc58993d73 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/rxjava/service/MoviePromiseService.java @@ -0,0 +1,15 @@ +package com.baeldung.rxjava.service; + +import java.util.List; + +import com.baeldung.model.Movie; + +import ratpack.exec.Promise; + +public interface MoviePromiseService { + + Promise> getMovies(); + + Promise getMovie(); + +} diff --git a/ratpack/src/main/java/com/baeldung/rxjava/service/impl/MovieObservableServiceImpl.java b/ratpack/src/main/java/com/baeldung/rxjava/service/impl/MovieObservableServiceImpl.java new file mode 100644 index 0000000000..817a33d857 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/rxjava/service/impl/MovieObservableServiceImpl.java @@ -0,0 +1,35 @@ +package com.baeldung.rxjava.service.impl; + +import com.baeldung.model.Movie; +import com.baeldung.rxjava.service.MovieObservableService; + +import rx.Observable; + +public class MovieObservableServiceImpl implements MovieObservableService { + + @Override + public Observable getMovie() { + Movie movie = new Movie(); + movie.setName("The Godfather"); + movie.setYear("1972"); + movie.setDirector("Coppola"); + movie.setRating(9.2); + return Observable.just(movie); + } + + @Override + public Observable getMovies() { + Movie movie = new Movie(); + movie.setName("The Godfather"); + movie.setYear("1972"); + movie.setDirector("Coppola"); + movie.setRating(9.2); + Movie movie2 = new Movie(); + movie2.setName("The Godfather Part 2"); + movie2.setYear("1974"); + movie2.setDirector("Coppola"); + movie2.setRating(9.0); + return Observable.just(movie, movie2); + + } +} diff --git a/ratpack/src/main/java/com/baeldung/rxjava/service/impl/MoviePromiseServiceImpl.java b/ratpack/src/main/java/com/baeldung/rxjava/service/impl/MoviePromiseServiceImpl.java new file mode 100644 index 0000000000..a66b1e79d6 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/rxjava/service/impl/MoviePromiseServiceImpl.java @@ -0,0 +1,41 @@ +package com.baeldung.rxjava.service.impl; + +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.model.Movie; +import com.baeldung.rxjava.service.MoviePromiseService; + +import ratpack.exec.Promise; + +public class MoviePromiseServiceImpl implements MoviePromiseService { + + @Override + public Promise getMovie() { + Movie movie = new Movie(); + movie.setName("The Godfather"); + movie.setYear("1972"); + movie.setDirector("Coppola"); + movie.setRating(9.2); + return Promise.value(movie); + } + + @Override + public Promise> getMovies() { + Movie movie = new Movie(); + movie.setName("The Godfather"); + movie.setYear("1972"); + movie.setDirector("Coppola"); + movie.setRating(9.2); + Movie movie2 = new Movie(); + movie2.setName("The Godfather Part 2"); + movie2.setYear("1974"); + movie2.setDirector("Coppola"); + movie2.setRating(9.0); + List movies = new ArrayList<>(); + movies.add(movie); + movies.add(movie2); + return Promise.value(movies); + } + +} From d6dc3f9941f448f337a109258b3c72acc5b29410 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Mon, 25 Feb 2019 22:49:29 +0530 Subject: [PATCH 112/496] BAEL-10944 Fixed failing tests --- pom.xml | 4 ++-- restx/pom.xml | 2 +- .../resources/specs/hello/should_admin_say_hello.spec.yaml | 2 +- .../resources/specs/hello/should_anyone_say_hello.spec.yaml | 2 +- .../resources/specs/hello/should_user1_say_hello.spec.yaml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 9b36b30f59..da7b260541 100644 --- a/pom.xml +++ b/pom.xml @@ -561,7 +561,7 @@ reactor-core rest-with-spark-java resteasy - + restx rule-engines/easy-rules rule-engines/openl-tablets @@ -1280,7 +1280,7 @@ reactor-core rest-with-spark-java resteasy - + restx rule-engines/easy-rules rule-engines/openl-tablets diff --git a/restx/pom.xml b/restx/pom.xml index cc503f89b6..16d785956a 100644 --- a/restx/pom.xml +++ b/restx/pom.xml @@ -151,6 +151,6 @@ 1.8 1.8 0.35-rc4 - 1.0.13 + 1.2.3 diff --git a/restx/src/test/resources/specs/hello/should_admin_say_hello.spec.yaml b/restx/src/test/resources/specs/hello/should_admin_say_hello.spec.yaml index 1b7b8f0f90..f50059903f 100644 --- a/restx/src/test/resources/specs/hello/should_admin_say_hello.spec.yaml +++ b/restx/src/test/resources/specs/hello/should_admin_say_hello.spec.yaml @@ -7,4 +7,4 @@ wts: GET message $RestxSession: {"_expires":"2013-09-27T01:18:00.822+02:00","principal":"admin","sessionKey":"e2b4430f-9541-4602-9a3a-413d17c56a6b"} then: | - {"message":"hello admin, it's 01:18:00"} + {"message":"hello admin, it's 04:48:00"} diff --git a/restx/src/test/resources/specs/hello/should_anyone_say_hello.spec.yaml b/restx/src/test/resources/specs/hello/should_anyone_say_hello.spec.yaml index 29b6faca34..4b84cee9f4 100644 --- a/restx/src/test/resources/specs/hello/should_anyone_say_hello.spec.yaml +++ b/restx/src/test/resources/specs/hello/should_anyone_say_hello.spec.yaml @@ -5,4 +5,4 @@ wts: - when: | GET hello?who=xavier then: | - {"message":"hello xavier, it's 01:18:00"} + {"message":"hello xavier, it's 04:48:00"} diff --git a/restx/src/test/resources/specs/hello/should_user1_say_hello.spec.yaml b/restx/src/test/resources/specs/hello/should_user1_say_hello.spec.yaml index 791a3a2776..825d1bb1b3 100644 --- a/restx/src/test/resources/specs/hello/should_user1_say_hello.spec.yaml +++ b/restx/src/test/resources/specs/hello/should_user1_say_hello.spec.yaml @@ -7,4 +7,4 @@ wts: GET message $RestxSession: {"_expires":"2013-09-27T01:18:00.822+02:00","principal":"user1","sessionKey":"e2b4430f-9541-4602-9a3a-413d17c56a6b"} then: | - {"message":"hello user1, it's 01:18:00"} + {"message":"hello user1, it's 04:48:00"} From f0a76420b6232b9f8143b0e7066520a4d0f33396 Mon Sep 17 00:00:00 2001 From: Karol Date: Mon, 25 Feb 2019 17:54:55 +0000 Subject: [PATCH 113/496] BAEL-2713 Serve Static Content in Spring WebFlux (#6404) --- spring-5-reactive/pom.xml | 22 +++++++++ spring-5-reactive/src/main/assets/index.html | 10 ++++ .../StaticContentApplication.java | 28 +++++++++++ .../staticcontent/StaticContentConfig.java | 35 +++++++++++++ ...lication-assets-custom-location.properties | 3 ++ .../src/main/resources/img/example-image.png | Bin 0 -> 17429 bytes .../src/main/resources/public/index.html | 10 ++++ ...cContentCustomLocationIntegrationTest.java | 39 +++++++++++++++ ...ContentDefaultLocationIntegrationTest.java | 46 ++++++++++++++++++ 9 files changed, 193 insertions(+) create mode 100644 spring-5-reactive/src/main/assets/index.html create mode 100644 spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentApplication.java create mode 100644 spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentConfig.java create mode 100644 spring-5-reactive/src/main/resources/application-assets-custom-location.properties create mode 100644 spring-5-reactive/src/main/resources/img/example-image.png create mode 100644 spring-5-reactive/src/main/resources/public/index.html create mode 100644 spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentCustomLocationIntegrationTest.java create mode 100644 spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentDefaultLocationIntegrationTest.java diff --git a/spring-5-reactive/pom.xml b/spring-5-reactive/pom.xml index a1eb6f4c8a..8d5324a673 100644 --- a/spring-5-reactive/pom.xml +++ b/spring-5-reactive/pom.xml @@ -124,6 +124,28 @@ + + maven-resources-plugin + 3.0.1 + + + copy-resources + validate + + copy-resources + + + + + src/main/assets + true + + + ${basedir}/target/classes/assets + + + + org.springframework.boot spring-boot-maven-plugin diff --git a/spring-5-reactive/src/main/assets/index.html b/spring-5-reactive/src/main/assets/index.html new file mode 100644 index 0000000000..047514df1c --- /dev/null +++ b/spring-5-reactive/src/main/assets/index.html @@ -0,0 +1,10 @@ + + + + + Baeldung: Static Content in Spring WebFlux + + +Example Spring Web Flux and web resources configuration + + \ No newline at end of file diff --git a/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentApplication.java b/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentApplication.java new file mode 100644 index 0000000000..31a3de4927 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentApplication.java @@ -0,0 +1,28 @@ +package com.baeldung.staticcontent; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.web.server.ServerHttpSecurity; +import org.springframework.security.web.server.SecurityWebFilterChain; + +import java.util.Collections; + +@SpringBootApplication +public class StaticContentApplication { + + public static void main(String[] args) { + SpringApplication app = new SpringApplication(StaticContentApplication.class); + app.setDefaultProperties(Collections.singletonMap("server.port", "8084")); + app.run(args); + } + + @Bean + public SecurityWebFilterChain staticContentSpringSecurityFilterChain(ServerHttpSecurity http) { + http.authorizeExchange() + .anyExchange() + .permitAll(); + return http.build(); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentConfig.java b/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentConfig.java new file mode 100644 index 0000000000..1fbb9958e7 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/staticcontent/StaticContentConfig.java @@ -0,0 +1,35 @@ +package com.baeldung.staticcontent; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; + +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; +import static org.springframework.web.reactive.function.server.ServerResponse.ok; + +@Configuration +public class StaticContentConfig { + + @Bean + public RouterFunction htmlRouter(@Value("classpath:/public/index.html") Resource html) { + return route( + GET("/"), + request -> ok() + .contentType(MediaType.TEXT_HTML) + .syncBody(html) + ); + } + + @Bean + public RouterFunction imgRouter() { + return RouterFunctions.resources("/img/**", new ClassPathResource("img/")); + } + +} diff --git a/spring-5-reactive/src/main/resources/application-assets-custom-location.properties b/spring-5-reactive/src/main/resources/application-assets-custom-location.properties new file mode 100644 index 0000000000..9a2dbb04d9 --- /dev/null +++ b/spring-5-reactive/src/main/resources/application-assets-custom-location.properties @@ -0,0 +1,3 @@ +# Use in Static content Example +spring.webflux.static-path-pattern = /assets/** +spring.resources.static-locations = classpath:/assets/ \ No newline at end of file diff --git a/spring-5-reactive/src/main/resources/img/example-image.png b/spring-5-reactive/src/main/resources/img/example-image.png new file mode 100644 index 0000000000000000000000000000000000000000..2fa6c7b8c5112fd99c91c94de9f7f5b9e24635aa GIT binary patch literal 17429 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 + + + + Baeldung: Static Content in Spring WebFlux + + +Example HTML file + + \ No newline at end of file diff --git a/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentCustomLocationIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentCustomLocationIntegrationTest.java new file mode 100644 index 0000000000..f40ff83738 --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentCustomLocationIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.staticcontent; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; + + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles("assets-custom-location") +public class StaticContentCustomLocationIntegrationTest { + + @Autowired + private WebTestClient client; + + @Test + public void whenRequestingHtmlFileFromCustomLocation_thenReturnThisFileAndTextHtmlContentType() throws Exception { + client.get() + .uri("/assets/index.html") + .exchange() + .expectStatus().isOk() + .expectHeader().valueEquals(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML_VALUE); + } + + @Test + public void whenRequestingMissingStaticResource_thenReturnNotFoundStatus() throws Exception { + client.get() + .uri("/assets/unknown.png") + .exchange() + .expectStatus().isNotFound(); + } + +} \ No newline at end of file diff --git a/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentDefaultLocationIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentDefaultLocationIntegrationTest.java new file mode 100644 index 0000000000..820d6e13ef --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/staticcontent/StaticContentDefaultLocationIntegrationTest.java @@ -0,0 +1,46 @@ +package com.baeldung.staticcontent; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; + + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class StaticContentDefaultLocationIntegrationTest { + + @Autowired + private WebTestClient client; + + @Test + public void whenRequestingHtmlFileFromDefaultLocation_thenReturnThisFileAndTextHtmlContentType() throws Exception { + client.get() + .uri("/index.html") + .exchange() + .expectStatus().isOk() + .expectHeader().valueEquals(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML_VALUE); + } + + @Test + public void whenRequestingPngImageFromImgLocation_thenReturnThisFileAndImagePngContentType() throws Exception { + client.get() + .uri("/img/example-image.png") + .exchange() + .expectStatus().isOk() + .expectHeader().valueEquals(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE); + } + + @Test + public void whenRequestingMissingStaticResource_thenReturnNotFoundStatus() throws Exception { + client.get() + .uri("/unknown.png") + .exchange() + .expectStatus().isNotFound(); + } + +} \ No newline at end of file From ad4ff82fa286c71255549c67eb830ca7e98127bb Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Tue, 26 Feb 2019 01:01:25 -0300 Subject: [PATCH 114/496] Building a web application with Spring Boot and Angular (#6396) * Initial Commit * Update pom.xml --- spring-boot-angular/pom.xml | 49 + .../baeldung/angularclient/.angular-cli.json | 60 + .../com/baeldung/angularclient/.editorconfig | 13 + .../com/baeldung/angularclient/.gitignore | 44 + .../java/com/baeldung/angularclient/README.md | 27 + .../angularclient/e2e/app.e2e-spec.ts | 14 + .../com/baeldung/angularclient/e2e/app.po.ts | 11 + .../angularclient/e2e/tsconfig.e2e.json | 14 + .../com/baeldung/angularclient/karma.conf.js | 33 + .../baeldung/angularclient/package-lock.json | 12627 ++++++++++++++++ .../com/baeldung/angularclient/package.json | 48 + .../baeldung/angularclient/protractor.conf.js | 28 + .../src/app/app-routing.module.ts | 15 + .../angularclient/src/app/app.component.css | 0 .../angularclient/src/app/app.component.html | 16 + .../src/app/app.component.spec.ts | 31 + .../angularclient/src/app/app.component.ts | 15 + .../angularclient/src/app/app.module.ts | 26 + .../angularclient/src/app/model/user.ts | 5 + .../src/app/service/user.service.spec.ts | 15 + .../src/app/service/user.service.ts | 22 + .../src/app/user-form/user-form.component.css | 0 .../app/user-form/user-form.component.html | 19 + .../app/user-form/user-form.component.spec.ts | 25 + .../src/app/user-form/user-form.component.ts | 26 + .../src/app/user-list/user-list.component.css | 0 .../app/user-list/user-list.component.html | 20 + .../app/user-list/user-list.component.spec.ts | 25 + .../src/app/user-list/user-list.component.ts | 23 + .../angularclient/src/assets/.gitkeep | 0 .../src/environments/environment.prod.ts | 3 + .../src/environments/environment.ts | 8 + .../baeldung/angularclient/src/favicon.ico | Bin 0 -> 5430 bytes .../com/baeldung/angularclient/src/index.html | 17 + .../com/baeldung/angularclient/src/main.ts | 12 + .../baeldung/angularclient/src/polyfills.ts | 79 + .../com/baeldung/angularclient/src/styles.css | 1 + .../angularclient/src/tsconfig.app.json | 13 + .../angularclient/src/tsconfig.spec.json | 19 + .../baeldung/angularclient/src/typings.d.ts | 5 + .../com/baeldung/angularclient/tsconfig.json | 19 + .../com/baeldung/angularclient/tslint.json | 143 + .../com/baeldung/application/Application.java | 28 + .../controllers/UserController.java | 31 + .../baeldung/application/entities/User.java | 43 + .../repositories/UserRepository.java | 10 + 46 files changed, 13682 insertions(+) create mode 100644 spring-boot-angular/pom.xml create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/.angular-cli.json create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/.editorconfig create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/.gitignore create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/README.md create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.e2e-spec.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.po.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/tsconfig.e2e.json create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/karma.conf.js create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/package-lock.json create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/package.json create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/protractor.conf.js create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app-routing.module.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.css create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.html create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.spec.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.module.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/model/user.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.spec.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.css create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.html create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.spec.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.css create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.html create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.spec.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/assets/.gitkeep create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.prod.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/favicon.ico create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/index.html create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/main.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/polyfills.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/styles.css create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.app.json create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.spec.json create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/src/typings.d.ts create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/tsconfig.json create mode 100644 spring-boot-angular/src/main/java/com/baeldung/angularclient/tslint.json create mode 100644 spring-boot-angular/src/main/java/com/baeldung/application/Application.java create mode 100644 spring-boot-angular/src/main/java/com/baeldung/application/controllers/UserController.java create mode 100644 spring-boot-angular/src/main/java/com/baeldung/application/entities/User.java create mode 100644 spring-boot-angular/src/main/java/com/baeldung/application/repositories/UserRepository.java diff --git a/spring-boot-angular/pom.xml b/spring-boot-angular/pom.xml new file mode 100644 index 0000000000..f2ed6d7718 --- /dev/null +++ b/spring-boot-angular/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + com.baeldung.springbootangular + springbootangular + 1.0 + jar + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + com.h2database + h2 + 1.4.197 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/.angular-cli.json b/spring-boot-angular/src/main/java/com/baeldung/angularclient/.angular-cli.json new file mode 100644 index 0000000000..3de2a62f41 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/.angular-cli.json @@ -0,0 +1,60 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "project": { + "name": "sampleapp" + }, + "apps": [ + { + "root": "src", + "outDir": "dist", + "assets": [ + "assets", + "favicon.ico" + ], + "index": "index.html", + "main": "main.ts", + "polyfills": "polyfills.ts", + "test": "test.ts", + "tsconfig": "tsconfig.app.json", + "testTsconfig": "tsconfig.spec.json", + "prefix": "app", + "styles": [ + "styles.css" + ], + "scripts": [], + "environmentSource": "environments/environment.ts", + "environments": { + "dev": "environments/environment.ts", + "prod": "environments/environment.prod.ts" + } + } + ], + "e2e": { + "protractor": { + "config": "./protractor.conf.js" + } + }, + "lint": [ + { + "project": "src/tsconfig.app.json", + "exclude": "**/node_modules/**" + }, + { + "project": "src/tsconfig.spec.json", + "exclude": "**/node_modules/**" + }, + { + "project": "e2e/tsconfig.e2e.json", + "exclude": "**/node_modules/**" + } + ], + "test": { + "karma": { + "config": "./karma.conf.js" + } + }, + "defaults": { + "styleExt": "css", + "component": {} + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/.editorconfig b/spring-boot-angular/src/main/java/com/baeldung/angularclient/.editorconfig new file mode 100644 index 0000000000..6e87a003da --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/.editorconfig @@ -0,0 +1,13 @@ +# Editor configuration, see http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/.gitignore b/spring-boot-angular/src/main/java/com/baeldung/angularclient/.gitignore new file mode 100644 index 0000000000..eabf65e51a --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/.gitignore @@ -0,0 +1,44 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/dist-server +/tmp +/out-tsc + +# dependencies +/node_modules + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# e2e +/e2e/*.js +/e2e/*.map + +# System Files +.DS_Store +Thumbs.db diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/README.md b/spring-boot-angular/src/main/java/com/baeldung/angularclient/README.md new file mode 100644 index 0000000000..6fec59bc13 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/README.md @@ -0,0 +1,27 @@ +# Sampleapp + +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.7.4. + +## Development server + +Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. + +## Code scaffolding + +Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. + +## Build + +Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. + +## Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Running end-to-end tests + +Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.e2e-spec.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.e2e-spec.ts new file mode 100644 index 0000000000..d72f8a4e91 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.e2e-spec.ts @@ -0,0 +1,14 @@ +import { AppPage } from './app.po'; + +describe('sampleapp App', () => { + let page: AppPage; + + beforeEach(() => { + page = new AppPage(); + }); + + it('should display welcome message', () => { + page.navigateTo(); + expect(page.getParagraphText()).toEqual('Welcome to app!'); + }); +}); diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.po.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.po.ts new file mode 100644 index 0000000000..82ea75ba50 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.po.ts @@ -0,0 +1,11 @@ +import { browser, by, element } from 'protractor'; + +export class AppPage { + navigateTo() { + return browser.get('/'); + } + + getParagraphText() { + return element(by.css('app-root h1')).getText(); + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/tsconfig.e2e.json b/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/tsconfig.e2e.json new file mode 100644 index 0000000000..1d9e5edf09 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/tsconfig.e2e.json @@ -0,0 +1,14 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/e2e", + "baseUrl": "./", + "module": "commonjs", + "target": "es5", + "types": [ + "jasmine", + "jasminewd2", + "node" + ] + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/karma.conf.js b/spring-boot-angular/src/main/java/com/baeldung/angularclient/karma.conf.js new file mode 100644 index 0000000000..af139fada3 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/karma.conf.js @@ -0,0 +1,33 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular/cli'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular/cli/plugins/karma') + ], + client:{ + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + reports: [ 'html', 'lcovonly' ], + fixWebpackSourcePaths: true + }, + angularCli: { + environment: 'dev' + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }); +}; diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/package-lock.json b/spring-boot-angular/src/main/java/com/baeldung/angularclient/package-lock.json new file mode 100644 index 0000000000..9ddc0a9ae0 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/package-lock.json @@ -0,0 +1,12627 @@ +{ + "name": "sampleapp", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@angular-devkit/build-optimizer": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.3.2.tgz", + "integrity": "sha512-U0BCZtThq5rUfY08shHXpxe8ZhSsiYB/cJjUvAWRTs/ORrs8pbngS6xwseQws8d/vHoVrtqGD9GU9h8AmFRERQ==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "source-map": "^0.5.6", + "typescript": "~2.6.2", + "webpack-sources": "^1.0.1" + }, + "dependencies": { + "typescript": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", + "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", + "dev": true + } + } + }, + "@angular-devkit/core": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-0.3.2.tgz", + "integrity": "sha512-zABk/iP7YX5SVbmK4e+IX7j2d0D37MQJQiKgWdV3JzfvVJhNJzddiirtT980pIafoq+KyvTgVwXtc+vnux0oeQ==", + "dev": true, + "requires": { + "ajv": "~5.5.1", + "chokidar": "^1.7.0", + "rxjs": "^5.5.6", + "source-map": "^0.5.6" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + } + } + }, + "@angular-devkit/schematics": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-0.3.2.tgz", + "integrity": "sha512-B6zZoqvHaTJy+vVdA6EtlxnCdGMa5elCa4j9lQLC3JI8DLvMXUWkCIPVbPzJ/GSRR9nsKWpvYMYaJyfBDUqfhw==", + "dev": true, + "requires": { + "@ngtools/json-schema": "^1.1.0", + "rxjs": "^5.5.6" + } + }, + "@angular/animations": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-5.2.11.tgz", + "integrity": "sha512-J7wKHkFn3wV28/Y1Qm4yjGXVCwXzj1JR5DRjGDTFnxTRacUFx7Nj0ApGhN0b2+V0NOvgxQOvEW415Y22kGoblw==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/cli": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-1.7.4.tgz", + "integrity": "sha512-URdb1QtnQf+Ievy93wjq7gE81s25BkWUwJFPey+YkphBA3G1lbCAQPiEh2pntBwaIKavgEuCw+Sf2YZdgTVhDA==", + "dev": true, + "requires": { + "@angular-devkit/build-optimizer": "0.3.2", + "@angular-devkit/core": "0.3.2", + "@angular-devkit/schematics": "0.3.2", + "@ngtools/json-schema": "1.2.0", + "@ngtools/webpack": "1.10.2", + "@schematics/angular": "0.3.2", + "@schematics/package-update": "0.3.2", + "ajv": "^6.1.1", + "autoprefixer": "^7.2.3", + "cache-loader": "^1.2.0", + "chalk": "~2.2.0", + "circular-dependency-plugin": "^4.2.1", + "clean-css": "^4.1.11", + "common-tags": "^1.3.1", + "copy-webpack-plugin": "~4.4.1", + "core-object": "^3.1.0", + "denodeify": "^1.2.1", + "ember-cli-string-utils": "^1.0.0", + "extract-text-webpack-plugin": "^3.0.2", + "file-loader": "^1.1.5", + "fs-extra": "^4.0.0", + "glob": "^7.0.3", + "html-webpack-plugin": "^2.29.0", + "istanbul-instrumenter-loader": "^3.0.0", + "karma-source-map-support": "^1.2.0", + "less": "^2.7.2", + "less-loader": "^4.0.5", + "license-webpack-plugin": "^1.0.0", + "loader-utils": "1.1.0", + "lodash": "^4.11.1", + "memory-fs": "^0.4.1", + "minimatch": "^3.0.4", + "node-modules-path": "^1.0.0", + "node-sass": "^4.7.2", + "nopt": "^4.0.1", + "opn": "~5.1.0", + "portfinder": "~1.0.12", + "postcss": "^6.0.16", + "postcss-import": "^11.0.0", + "postcss-loader": "^2.0.10", + "postcss-url": "^7.1.2", + "raw-loader": "^0.5.1", + "resolve": "^1.1.7", + "rxjs": "^5.5.6", + "sass-loader": "^6.0.6", + "semver": "^5.1.0", + "silent-error": "^1.0.0", + "source-map-support": "^0.4.1", + "style-loader": "^0.19.1", + "stylus": "^0.54.5", + "stylus-loader": "^3.0.1", + "uglifyjs-webpack-plugin": "^1.1.8", + "url-loader": "^0.6.2", + "webpack": "~3.11.0", + "webpack-dev-middleware": "~1.12.0", + "webpack-dev-server": "~2.11.0", + "webpack-merge": "^4.1.0", + "webpack-sources": "^1.0.0", + "webpack-subresource-integrity": "^1.0.1" + } + }, + "@angular/common": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-5.2.11.tgz", + "integrity": "sha512-LniJjGAeftUJDJh+2+LEjltcGen08C/VMxQ/eUYmesytKy1sN+MWzh3GbpKfEWtWmyUsYTG9lAAJNo3L3jPwsw==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/compiler": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-5.2.11.tgz", + "integrity": "sha512-ICvB1ud1mxaXUYLb8vhJqiLhGBVocAZGxoHTglv6hMkbrRYcnlB3FZJFOzBvtj+krkd1jamoYLI43UAmesqQ6Q==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/compiler-cli": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-5.2.11.tgz", + "integrity": "sha512-dwrQ0yxoCM/XzKzlm7pTsyg4/6ECjT9emZufGj8t12bLMO8NDn1IJOsqXJA1+onEgQKhlr0Ziwi+96TvDTb1Cg==", + "dev": true, + "requires": { + "chokidar": "^1.4.2", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "tsickle": "^0.27.2" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "@angular/core": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-5.2.11.tgz", + "integrity": "sha512-h2vpvXNAdOqKzbVaZcHnHGMT5A8uDnizk6FgGq6SPyw9s3d+/VxZ9LJaPjUk3g2lICA7og1tUel+2YfF971MlQ==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/forms": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-5.2.11.tgz", + "integrity": "sha512-wBllFlIubPclAFRXUc84Kc7TMeKOftzrQraVZ7ooTNeFLLa/FZLN2K8HGyRde8X/XDsMu1XAmjNfkz++spwTzA==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/http": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-5.2.11.tgz", + "integrity": "sha512-eR7wNXh1+6MpcQNb3sq4bJVX03dx50Wl3kpPG+Q7N1VSL0oPQSobaTrR17ac3oFCEfSJn6kkUCqtUXha6wcNHg==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/language-service": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-5.2.11.tgz", + "integrity": "sha512-tgnFAhwBmUs1W0dmcmlBmUlMaOgkoyuSdrcF23lz8W5+nSLb+LnbH5a3blU2NVqA4ESvLKQkPW5dpKa/LuhrPQ==", + "dev": true + }, + "@angular/platform-browser": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-5.2.11.tgz", + "integrity": "sha512-6YZ4IpBFqXx88vEzBZG2WWnaSYXbFWDgG0iT+bZPHAfwsbmqbcMcs7Ogu+XZ4VmK02dTqbrFh7U4P2W+sqrzow==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/platform-browser-dynamic": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-5.2.11.tgz", + "integrity": "sha512-5kKPNULcXNwkyBjpHfF+pq+Yxi8Zl866YSOK9t8txoiQ9Ctw97kMkEJcTetk6MJgBp/NP3YyjtoTAm8oXLerug==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/router": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-5.2.11.tgz", + "integrity": "sha512-NT8xYl7Vr3qPygisek3PlXqNROEjg48GXOEsDEc7c8lDBo3EB9Tf328fWJD0GbLtXZNhmmNNxwIe+qqPFFhFAA==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@ngtools/json-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.2.0.tgz", + "integrity": "sha512-pMh+HDc6mOjUO3agRfB1tInimo7hf67u+0Cska2bfXFe6oU7rSMnr5PLVtiZVgwMoBHpx/6XjBymvcnWPo2Uzg==", + "dev": true + }, + "@ngtools/webpack": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-1.10.2.tgz", + "integrity": "sha512-3u2zg2rarG3qNLSukBClGADWuq/iNn5SQtlSeAbfKzwBeyLGbF0gN1z1tVx1Bcr8YwFzR6NdRePQmJGcoqq1fg==", + "dev": true, + "requires": { + "chalk": "~2.2.0", + "enhanced-resolve": "^3.1.0", + "loader-utils": "^1.0.2", + "magic-string": "^0.22.3", + "semver": "^5.3.0", + "source-map": "^0.5.6", + "tree-kill": "^1.0.0", + "webpack-sources": "^1.1.0" + } + }, + "@schematics/angular": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-0.3.2.tgz", + "integrity": "sha512-Elrk0BA951s0ScFZU0AWrpUeJBYVR52DZ1QTIO5R0AhwEd1PW4olI8szPLGQlVW5Sd6H0FA/fyFLIvn2r9v6Rw==", + "dev": true, + "requires": { + "typescript": "~2.6.2" + }, + "dependencies": { + "typescript": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", + "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", + "dev": true + } + } + }, + "@schematics/package-update": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@schematics/package-update/-/package-update-0.3.2.tgz", + "integrity": "sha512-7aVP4994Hu8vRdTTohXkfGWEwLhrdNP3EZnWyBootm5zshWqlQojUGweZe5zwewsKcixeVOiy2YtW+aI4aGSLA==", + "dev": true, + "requires": { + "rxjs": "^5.5.6", + "semver": "^5.3.0", + "semver-intersect": "^1.1.2" + } + }, + "@types/jasmine": { + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.16.tgz", + "integrity": "sha512-056oRlBBp7MDzr+HoU5su099s/s7wjZ3KcHxLfv+Byqb9MwdLUvsfLgw1VS97hsh3ddxSPyQu+olHMnoVTUY6g==", + "dev": true + }, + "@types/jasminewd2": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.6.tgz", + "integrity": "sha512-2ZOKrxb8bKRmP/po5ObYnRDgFE4i+lQiEB27bAMmtMWLgJSqlIDqlLx6S0IRorpOmOPRQ6O80NujTmQAtBkeNw==", + "dev": true, + "requires": { + "@types/jasmine": "*" + } + }, + "@types/node": { + "version": "6.0.118", + "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.118.tgz", + "integrity": "sha512-N33cKXGSqhOYaPiT4xUGsYlPPDwFtQM/6QxJxuMXA/7BcySW+lkn2yigWP7vfs4daiL/7NJNU6DMCqg5N4B+xQ==", + "dev": true + }, + "@types/q": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", + "dev": true + }, + "@types/selenium-webdriver": { + "version": "2.53.43", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-2.53.43.tgz", + "integrity": "sha512-UBYHWph6P3tutkbXpW6XYg9ZPbTKjw/YC2hGG1/GEvWwTbvezBUv3h+mmUFw79T3RFPnmedpiXdOBbXX+4l0jg==", + "dev": true + }, + "@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=", + "dev": true + }, + "@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "^4.0.3" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "addressparser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", + "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=", + "dev": true, + "optional": true + }, + "adm-zip": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", + "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "dependencies": { + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "ajv-keywords": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.3.0.tgz", + "integrity": "sha512-CMzN9S62ZOO4sA/mJZIO4S++ZM7KFWzH3PPWkveLhy4OZ9i1/VatgwWMD46w/XbGCBy7Ye0gCk+Za6mmyfKK7g==", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "amqplib": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.3.tgz", + "integrity": "sha512-ZOdUhMxcF+u62rPI+hMtU1NBXSDFQ3eCJJrenamtdQ7YYwh7RZJHOIM1gonVbZ5PyVdYH4xqBPje9OYqk7fnqw==", + "dev": true, + "optional": true, + "requires": { + "bitsyntax": "~0.1.0", + "bluebird": "^3.5.2", + "buffer-more-ints": "~1.0.0", + "readable-stream": "1.x >=1.1.9", + "safe-buffer": "~5.1.2", + "url-parse": "~1.4.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true, + "optional": true + } + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "app-root-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.1.0.tgz", + "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=", + "dev": true + }, + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true, + "requires": { + "default-require-extensions": "^1.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true, + "optional": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true, + "optional": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.7.tgz", + "integrity": "sha512-2mP3TwtkY/aTv5X3ZsMpNAbOnyoC/aMJwJSoaELPkHId0nSQgFcnU4dRW3isxiz7+zBexk0ym3WNVjMiQBnJSw==", + "dev": true, + "optional": true + }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true, + "optional": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.6.tgz", + "integrity": "sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ==", + "dev": true, + "requires": { + "browserslist": "^2.11.3", + "caniuse-lite": "^1.0.30000805", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^6.0.17", + "postcss-value-parser": "^3.2.3" + } + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "axios": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.15.3.tgz", + "integrity": "sha1-LJ1jiy4ZGgjqHWzJiOrda6W9wFM=", + "dev": true, + "optional": true, + "requires": { + "follow-redirects": "1.0.0" + }, + "dependencies": { + "follow-redirects": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.0.0.tgz", + "integrity": "sha1-jjQpjL0uF28lTv/sdaHHjMhJ/Tc=", + "dev": true, + "optional": true, + "requires": { + "debug": "^2.2.0" + } + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "dev": true + }, + "bitsyntax": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", + "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", + "dev": true, + "optional": true, + "requires": { + "buffer-more-ints": "~1.0.0", + "debug": "~2.6.9", + "safe-buffer": "~5.1.2" + } + }, + "bl": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", + "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "~2.0.5" + }, + "dependencies": { + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true, + "optional": true + } + } + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "optional": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "blocking-proxy": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-0.0.5.tgz", + "integrity": "sha1-RikF4Nz76pcPQao3Ij3anAexkSs=", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.x.x" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000792", + "electron-to-chromium": "^1.3.30" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-more-ints": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", + "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "buildmail": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-4.0.1.tgz", + "integrity": "sha1-h393OLeHKYccmhBeO4N9K+EaenI=", + "dev": true, + "optional": true, + "requires": { + "addressparser": "1.0.1", + "libbase64": "0.1.0", + "libmime": "3.0.0", + "libqp": "1.1.0", + "nodemailer-fetch": "1.6.0", + "nodemailer-shared": "1.1.0", + "punycode": "1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + } + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "cache-loader": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-1.2.5.tgz", + "integrity": "sha512-enWKEQ4kO3YreDFd7AtVRjtJBmNiqh/X9hVDReu0C4qm8gsGmySkwuWtdc+N5O+vq5FzxL1mIZc30NyXCB7o/Q==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "mkdirp": "^0.5.1", + "neo-async": "^2.5.0", + "schema-utils": "^0.4.2" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caniuse-lite": { + "version": "1.0.30000932", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000932.tgz", + "integrity": "sha512-4bghJFItvzz8m0T3lLZbacmEY9X1Z2AtIzTr7s7byqZIOumASfr4ynDx7rtm0J85nDmx8vsgR6vnaSoeU8Oh0A==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.2.2.tgz", + "integrity": "sha512-LvixLAQ4MYhbf7hgL4o5PeK32gJKvVzDRiSNIApDofQvyhl8adgG2lJVXn4+ekQoK7HL9RF8lqxwerpe0x2pCw==", + "dev": true, + "requires": { + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "chownr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-dependency-plugin": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-4.4.0.tgz", + "integrity": "sha512-yEFtUNUYT4jBykEX5ZOHw+5goA3glGZr9wAXIQqoyakjz5H5TeUmScnWRc52douAhb9eYzK3s7V6bXfNnjFdzg==", + "dev": true + }, + "circular-json": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-deep": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", + "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.0", + "shallow-clone": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "codelyzer": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.5.0.tgz", + "integrity": "sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==", + "dev": true, + "requires": { + "app-root-path": "^2.1.0", + "css-selector-tokenizer": "^0.7.0", + "cssauron": "^1.4.0", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.1" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + } + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combine-lists": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", + "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", + "dev": true, + "requires": { + "lodash": "^4.5.0" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compressible": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.15.tgz", + "integrity": "sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==", + "dev": true, + "requires": { + "mime-db": ">= 1.36.0 < 2" + } + }, + "compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.14", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + }, + "dependencies": { + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.4.3.tgz", + "integrity": "sha512-v4THQ24Tks2NkyOvZuFDgZVfDD9YaA9rwYLZTrWg2GHIA8lrH5DboEyeoorh5Skki+PUbgSmnsCwhMWqYrQZrA==", + "dev": true, + "requires": { + "cacache": "^10.0.1", + "find-cache-dir": "^1.0.0", + "globby": "^7.1.1", + "is-glob": "^4.0.0", + "loader-utils": "^1.1.0", + "minimatch": "^3.0.4", + "p-limit": "^1.0.0", + "serialize-javascript": "^1.4.0" + }, + "dependencies": { + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + } + } + }, + "core-js": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.3.tgz", + "integrity": "sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ==" + }, + "core-object": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/core-object/-/core-object-3.1.5.tgz", + "integrity": "sha512-sA2/4+/PZ/KV6CKgjrVrrUVBKCkdDO02CUlQ0YKTQoYUwPYNOtOAcWlbYhd5v/1JqYaA6oZ4sDlOU4ppVw6Wbg==", + "dev": true, + "requires": { + "chalk": "^2.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "optional": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "optional": true, + "requires": { + "boom": "2.x.x" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-parse": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz", + "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=", + "dev": true + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-selector-tokenizer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", + "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", + "dev": true, + "requires": { + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" + } + }, + "css-what": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz", + "integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ==", + "dev": true + }, + "cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", + "dev": true, + "requires": { + "through": "X.X.X" + } + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "^0.10.9" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "data-uri-to-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.0.tgz", + "integrity": "sha512-YbKCNLPPP4inc0E5If4OaalBc7gpaM2MRv77Pv2VThVComLKfbGYtJcdDCViDyp1Wd4SebhHLz94vp91zbK6bw==", + "dev": true, + "optional": true, + "requires": { + "@types/node": "^8.0.7" + }, + "dependencies": { + "@types/node": { + "version": "8.10.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.39.tgz", + "integrity": "sha512-rE7fktr02J8ybFf6eysife+WF+L4sAHWzw09DgdCebEu+qDwMvv4zl6Bc+825ttGZP73kCKxa3dhJOoGJ8+5mA==", + "dev": true, + "optional": true + } + } + }, + "date-format": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", + "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true, + "optional": true + }, + "default-require-extensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", + "dev": true, + "requires": { + "strip-bom": "^2.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "dev": true, + "optional": true, + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true, + "optional": true + } + } + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", + "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "double-ended-queue": { + "version": "2.1.0-0", + "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", + "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", + "dev": true, + "optional": true + }, + "duplexify": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.109", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.109.tgz", + "integrity": "sha512-1qhgVZD9KIULMyeBkbjU/dWmm30zpPUfdWZfVO3nPhbtqMHJqHr4Ua5wBcWtAymVFrUCuAJxjMF1OhG+bR21Ow==", + "dev": true + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "ember-cli-string-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ember-cli-string-utils/-/ember-cli-string-utils-1.1.0.tgz", + "integrity": "sha1-ObZ3/CgF9VFzc1N2/O8njqpEUqE=", + "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.1.5.tgz", + "integrity": "sha512-D06ivJkYxyRrcEe0bTpNnBQNgP9d3xog+qZlLbui8EsMr/DouQpf5o9FzJnWYHEYE0YsFHllUv2R1dkgYZXHcA==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "uws": "~9.14.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-client": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.1.6.tgz", + "integrity": "sha512-hnuHsFluXnsKOndS4Hv6SvUrgdYx1pk2NqfaDMW+GWdgfU3+/V25Cj7I8a0x92idSpa5PIhJRKxPvp9mnoLsfg==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "object-assign": "^4.0.1", + "tapable": "^0.2.7" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.47", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.47.tgz", + "integrity": "sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-promise": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", + "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "dev": true, + "optional": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "dev": true + }, + "events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", + "dev": true + }, + "eventsource": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", + "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", + "dev": true, + "requires": { + "original": ">=0.0.5" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-braces": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", + "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "dev": true, + "requires": { + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" + }, + "dependencies": { + "braces": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", + "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "dev": true, + "requires": { + "expand-range": "^0.1.0" + } + }, + "expand-range": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "dev": true, + "requires": { + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" + } + }, + "is-number": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", + "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", + "dev": true + }, + "repeat-string": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", + "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", + "dev": true + } + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + } + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "extract-text-webpack-plugin": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz", + "integrity": "sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ==", + "dev": true, + "requires": { + "async": "^2.4.1", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0", + "webpack-sources": "^1.0.1" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "^5.0.0" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true, + "optional": true + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "file-loader": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^0.4.5" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" + } + }, + "follow-redirects": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", + "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", + "dev": true, + "requires": { + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-access": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "requires": { + "null-check": "^1.0.0" + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true + } + } + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "optional": true, + "requires": { + "globule": "^1.0.0" + } + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "optional": true, + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "optional": true, + "requires": { + "is-property": "^1.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-uri": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.3.tgz", + "integrity": "sha512-x5j6Ks7FOgLD/GlvjKwgu7wdmMR55iuRHhn8hj/+gA+eSbxQvZ+AEomq+3MgVEZj1vpi738QahGbCCSIDtXtkw==", + "dev": true, + "optional": true, + "requires": { + "data-uri-to-buffer": "2", + "debug": "4", + "extend": "~3.0.2", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "optional": true + }, + "readable-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", + "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "dev": true, + "optional": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + } + }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "dev": true, + "optional": true, + "requires": { + "glob": "~7.1.1", + "lodash": "~4.17.10", + "minimatch": "~3.0.2" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "handle-thing": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", + "dev": true + }, + "handlebars": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", + "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", + "dev": true, + "requires": { + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "optional": true, + "requires": { + "ajv": "^4.9.1", + "har-schema": "^1.0.5" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "optional": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "optional": true, + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hipchat-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hipchat-notifier/-/hipchat-notifier-1.1.0.tgz", + "integrity": "sha1-ttJJdVQ3wZEII2d5nTupoPI7Ix4=", + "dev": true, + "optional": true, + "requires": { + "lodash": "^4.0.0", + "request": "^2.0.0" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + } + }, + "html-webpack-plugin": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-2.30.1.tgz", + "integrity": "sha1-f5xCG36pHsRg9WUn1430hO51N9U=", + "dev": true, + "requires": { + "bluebird": "^3.4.7", + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "toposort": "^1.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + } + } + }, + "htmlparser2": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", + "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", + "dev": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.1", + "domutils": "1.1", + "readable-stream": "1.0" + }, + "dependencies": { + "domutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", + "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-parser-js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", + "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", + "dev": true + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "http-proxy-middleware": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", + "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", + "dev": true, + "requires": { + "http-proxy": "^1.16.2", + "is-glob": "^3.1.0", + "lodash": "^4.17.2", + "micromatch": "^2.3.11" + }, + "dependencies": { + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "httpntlm": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", + "dev": true, + "requires": { + "httpreq": ">=0.4.22", + "underscore": "~1.7.0" + } + }, + "httpreq": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", + "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=", + "dev": true + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "dev": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "dev": true, + "requires": { + "pkg-dir": "^2.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "dev": true, + "optional": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", + "dev": true, + "optional": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "internal-ip": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz", + "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", + "dev": true, + "requires": { + "meow": "^3.3.0" + } + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true, + "optional": true + }, + "is-my-json-valid": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", + "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", + "dev": true, + "optional": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-api": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", + "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", + "dev": true, + "requires": { + "async": "^2.1.4", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.1", + "istanbul-lib-hook": "^1.2.2", + "istanbul-lib-instrument": "^1.10.2", + "istanbul-lib-report": "^1.1.5", + "istanbul-lib-source-maps": "^1.2.6", + "istanbul-reports": "^1.5.1", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" + } + }, + "istanbul-instrumenter-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", + "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", + "dev": true, + "requires": { + "convert-source-map": "^1.5.0", + "istanbul-lib-instrument": "^1.7.3", + "loader-utils": "^1.1.0", + "schema-utils": "^0.3.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "^5.0.0" + } + } + } + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", + "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", + "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", + "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", + "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } + }, + "jasmine": { + "version": "2.99.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.99.0.tgz", + "integrity": "sha1-jKctEC5jm4Z8ZImFbg4YqceqQrc=", + "dev": true, + "requires": { + "exit": "^0.1.2", + "glob": "^7.0.6", + "jasmine-core": "~2.99.0" + }, + "dependencies": { + "jasmine-core": { + "version": "2.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz", + "integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=", + "dev": true + } + } + }, + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "dev": true + }, + "jasmine-spec-reporter": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", + "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", + "dev": true, + "requires": { + "colors": "1.1.2" + } + }, + "jasminewd2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", + "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=", + "dev": true + }, + "js-base64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", + "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", + "dev": true, + "optional": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "optional": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true, + "optional": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "karma": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/karma/-/karma-2.0.5.tgz", + "integrity": "sha512-rECezBeY7mjzGUWhFlB7CvPHgkHJLXyUmWg+6vHCEsdWNUTnmiS6jRrIMcJEWgU2DUGZzGWG0bTRVky8fsDTOA==", + "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.4", + "log4js": "^2.5.3", + "mime": "^1.3.4", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.0.4", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.2.1" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "karma-chrome-launcher": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz", + "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==", + "dev": true, + "requires": { + "fs-access": "^1.0.0", + "which": "^1.2.1" + } + }, + "karma-coverage-istanbul-reporter": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", + "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", + "dev": true, + "requires": { + "istanbul-api": "^1.3.1", + "minimatch": "^3.0.4" + } + }, + "karma-jasmine": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-1.1.2.tgz", + "integrity": "sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=", + "dev": true + }, + "karma-jasmine-html-reporter": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz", + "integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=", + "dev": true, + "requires": { + "karma-jasmine": "^1.0.2" + } + }, + "karma-source-map-support": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.3.0.tgz", + "integrity": "sha512-HcPqdAusNez/ywa+biN4EphGz62MmQyPggUsDfsHqa7tSe4jdsxgvTKuDfIazjL+IOxpVWyT7Pr4dhAV+sxX5Q==", + "dev": true, + "requires": { + "source-map-support": "^0.5.5" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "less": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", + "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", + "dev": true, + "requires": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "mime": "^1.2.11", + "mkdirp": "^0.5.0", + "promise": "^7.1.1", + "request": "2.81.0", + "source-map": "^0.5.3" + } + }, + "less-loader": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-4.1.0.tgz", + "integrity": "sha512-KNTsgCE9tMOM70+ddxp9yyt9iHqgmSs0yTZc5XH5Wo+g80RWRIYNqE58QJKm/yMud5wZEvz50ugRDuzVIkyahg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "loader-utils": "^1.1.0", + "pify": "^3.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "optional": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "libbase64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", + "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=", + "dev": true + }, + "libmime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/libmime/-/libmime-3.0.0.tgz", + "integrity": "sha1-UaGp50SOy9Ms2lRCFnW7IbwJPaY=", + "dev": true, + "requires": { + "iconv-lite": "0.4.15", + "libbase64": "0.1.0", + "libqp": "1.1.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "integrity": "sha1-/iZaIYrGpXz+hUkn6dBMGYJe3es=", + "dev": true + } + } + }, + "libqp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", + "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=", + "dev": true + }, + "license-webpack-plugin": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-1.5.0.tgz", + "integrity": "sha512-Of/H79rZqm2aeg4RnP9SMSh19qkKemoLT5VaJV58uH5AxeYWEcBgGFs753JEJ/Hm6BPvQVfIlrrjoBwYj8p7Tw==", + "dev": true, + "requires": { + "ejs": "^2.5.7" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true, + "optional": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "lodash.mergewith": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", + "dev": true, + "optional": true + }, + "lodash.tail": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", + "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", + "dev": true + }, + "log4js": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-2.11.0.tgz", + "integrity": "sha512-z1XdwyGFg8/WGkOyF6DPJjivCWNLKrklGdViywdYnSKOvgtEBo2UyEMZS5sD2mZrQlU3TvO8wDWLc8mzE1ncBQ==", + "dev": true, + "requires": { + "amqplib": "^0.5.2", + "axios": "^0.15.3", + "circular-json": "^0.5.4", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "hipchat-notifier": "^1.1.0", + "loggly": "^1.1.0", + "mailgun-js": "^0.18.0", + "nodemailer": "^2.5.0", + "redis": "^2.7.1", + "semver": "^5.5.0", + "slack-node": "~0.2.0", + "streamroller": "0.7.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "loggly": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/loggly/-/loggly-1.1.1.tgz", + "integrity": "sha1-Cg/B0/o6XsRP3HuJe+uipGlc6+4=", + "dev": true, + "optional": true, + "requires": { + "json-stringify-safe": "5.0.x", + "request": "2.75.x", + "timespan": "2.3.x" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "optional": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true, + "optional": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "form-data": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.0.0.tgz", + "integrity": "sha1-bwrrrcxdoWwT4ezBETfYX5uIOyU=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.11" + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "optional": true, + "requires": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", + "dev": true, + "optional": true + }, + "request": { + "version": "2.75.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.75.0.tgz", + "integrity": "sha1-0rgmiihtoT6qXQGt9dGMyQ9lfZM=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "bl": "~1.1.2", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.0.0", + "har-validator": "~2.0.6", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "node-uuid": "~1.4.7", + "oauth-sign": "~0.8.1", + "qs": "~6.2.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "~0.4.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "optional": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true, + "optional": true + } + } + }, + "loglevel": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "magic-string": { + "version": "0.22.5", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", + "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", + "dev": true, + "requires": { + "vlq": "^0.2.2" + } + }, + "mailcomposer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-4.0.1.tgz", + "integrity": "sha1-DhxEsqB890DuF9wUm6AJ8Zyt/rQ=", + "dev": true, + "optional": true, + "requires": { + "buildmail": "4.0.1", + "libmime": "3.0.0" + } + }, + "mailgun-js": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/mailgun-js/-/mailgun-js-0.18.1.tgz", + "integrity": "sha512-lvuMP14u24HS2uBsJEnzSyPMxzU2b99tQsIx1o6QNjqxjk8b3WvR+vq5oG1mjqz/IBYo+5gF+uSoDS0RkMVHmg==", + "dev": true, + "optional": true, + "requires": { + "async": "~2.6.0", + "debug": "~3.1.0", + "form-data": "~2.3.0", + "inflection": "~1.12.0", + "is-stream": "^1.1.0", + "path-proxy": "~1.0.0", + "promisify-call": "^2.0.2", + "proxy-agent": "~3.0.0", + "tsscmp": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + } + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "dev": true + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dev": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "dev": true, + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "nan": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=", + "dev": true, + "optional": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", + "dev": true + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "dev": true, + "optional": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "optional": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "optional": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "optional": true, + "requires": { + "abbrev": "1" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "optional": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true, + "optional": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "optional": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true, + "optional": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "optional": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "node-libs-browser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", + "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node-modules-path": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/node-modules-path/-/node-modules-path-1.0.2.tgz", + "integrity": "sha512-6Gbjq+d7uhkO7epaKi5DNgUJn7H0gEyA4Jg0Mo1uQOi3Rk50G83LtmhhFyw0LxnAFhtlspkiiw52ISP13qzcBg==", + "dev": true + }, + "node-sass": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz", + "integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==", + "dev": true, + "optional": true, + "requires": { + "async-foreach": "^0.1.3", + "chalk": "^1.1.1", + "cross-spawn": "^3.0.0", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "in-publish": "^2.0.0", + "lodash.assign": "^4.2.0", + "lodash.clonedeep": "^4.3.2", + "lodash.mergewith": "^4.6.0", + "meow": "^3.7.0", + "mkdirp": "^0.5.1", + "nan": "^2.10.0", + "node-gyp": "^3.8.0", + "npmlog": "^4.0.0", + "request": "^2.88.0", + "sass-graph": "^2.2.4", + "stdout-stream": "^1.4.0", + "true-case-path": "^1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "optional": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "optional": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "optional": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "optional": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "optional": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true, + "optional": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "optional": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "optional": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "optional": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "nodemailer": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-2.7.2.tgz", + "integrity": "sha1-8kLmSa7q45tsftdA73sGHEBNMPk=", + "dev": true, + "optional": true, + "requires": { + "libmime": "3.0.0", + "mailcomposer": "4.0.1", + "nodemailer-direct-transport": "3.3.2", + "nodemailer-shared": "1.1.0", + "nodemailer-smtp-pool": "2.8.2", + "nodemailer-smtp-transport": "2.7.2", + "socks": "1.1.9" + }, + "dependencies": { + "smart-buffer": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-1.1.15.tgz", + "integrity": "sha1-fxFLW2X6s+KjWqd1uxLw0cZJvxY=", + "dev": true, + "optional": true + }, + "socks": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-1.1.9.tgz", + "integrity": "sha1-Yo1+TQSRJDVEWsC25Fk3bLPm1pE=", + "dev": true, + "optional": true, + "requires": { + "ip": "^1.1.2", + "smart-buffer": "^1.0.4" + } + } + } + }, + "nodemailer-direct-transport": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-3.3.2.tgz", + "integrity": "sha1-6W+vuQNYVglH5WkBfZfmBzilCoY=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-fetch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=", + "dev": true + }, + "nodemailer-shared": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", + "dev": true, + "requires": { + "nodemailer-fetch": "1.6.0" + } + }, + "nodemailer-smtp-pool": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-pool/-/nodemailer-smtp-pool-2.8.2.tgz", + "integrity": "sha1-LrlNbPhXgLG0clzoU7nL1ejajHI=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-smtp-transport": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz", + "integrity": "sha1-A9ccdjFPFKx9vHvwM6am0W1n+3c=", + "dev": true, + "optional": true, + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-wellknown": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=", + "dev": true + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.2.tgz", + "integrity": "sha512-YcMnjqeoUckXTPKZSAsPjUPLxH85XotbpqK3w4RyCwdFQSU5FxxBys8buehkSfg0j9fKvV1hn7O0+8reEgkAiw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "opn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", + "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "optional": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true, + "optional": true + } + } + }, + "options": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", + "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", + "dev": true + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pac-proxy-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", + "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", + "dev": true, + "optional": true, + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "optional": true + } + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "dev": true, + "optional": true, + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } + }, + "pako": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", + "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==", + "dev": true + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, + "parse-asn1": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.3.tgz", + "integrity": "sha512-VrPoetlz7B/FqjBLD2f5wBVZvsZVLnRUrxVLfRYhGXCODa/NWE4p3Wp+6+aV3ZPL3KM7/OZmxDIwwijD7yuucg==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-proxy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-proxy/-/path-proxy-1.0.0.tgz", + "integrity": "sha1-GOijaFn8nS8aU7SN7hOFQ8Ag3l4=", + "dev": true, + "optional": true, + "requires": { + "inflection": "~1.3.0" + }, + "dependencies": { + "inflection": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.3.8.tgz", + "integrity": "sha1-y9Fg2p91sUw8xjV41POWeEvzAU4=", + "dev": true, + "optional": true + } + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true, + "optional": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "portfinder": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", + "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==", + "dev": true, + "requires": { + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-import": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz", + "integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==", + "dev": true, + "requires": { + "postcss": "^6.0.1", + "postcss-value-parser": "^3.2.3", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-load-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", + "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", + "dev": true, + "requires": { + "cosmiconfig": "^4.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.6.tgz", + "integrity": "sha512-hgiWSc13xVQAq25cVw80CH0l49ZKlAnU1hKPOdRrNj89bokRr/bZF2nT+hebPPF9c9xs8c3gw3Fr2nxtmXYnNg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^6.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^0.4.0" + } + }, + "postcss-url": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-7.3.2.tgz", + "integrity": "sha512-QMV5mA+pCYZQcUEPQkmor9vcPQ2MT+Ipuu8qdi1gVxbNiIiErEGft+eny1ak19qALoBkccS5AHaCaCDzh7b9MA==", + "dev": true, + "requires": { + "mime": "^1.4.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.0", + "postcss": "^6.0.1", + "xxhashjs": "^0.2.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, + "requires": { + "renderkid": "^2.0.1", + "utila": "~0.4" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "optional": true, + "requires": { + "asap": "~2.0.3" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promisify-call": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/promisify-call/-/promisify-call-2.0.4.tgz", + "integrity": "sha1-1IwtRWUszM1SgB3ey9UzptS9X7o=", + "dev": true, + "optional": true, + "requires": { + "with-callback": "^1.0.2" + } + }, + "protractor": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.1.2.tgz", + "integrity": "sha1-myIXQXCaTGLVzVPGqt1UpxE36V8=", + "dev": true, + "requires": { + "@types/node": "^6.0.46", + "@types/q": "^0.0.32", + "@types/selenium-webdriver": "~2.53.39", + "blocking-proxy": "0.0.5", + "chalk": "^1.1.3", + "glob": "^7.0.3", + "jasmine": "^2.5.3", + "jasminewd2": "^2.1.0", + "optimist": "~0.6.0", + "q": "1.4.1", + "saucelabs": "~1.3.0", + "selenium-webdriver": "3.0.1", + "source-map-support": "~0.4.0", + "webdriver-js-extender": "^1.0.0", + "webdriver-manager": "^12.0.6" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "webdriver-manager": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.1.tgz", + "integrity": "sha512-L9TEQmZs6JbMMRQI1w60mfps265/NCr0toYJl7p/R2OAk6oXAfwI6jqYP7EWae+d7Ad2S2Aj4+rzxoSjqk3ZuA==", + "dev": true, + "requires": { + "adm-zip": "^0.4.9", + "chalk": "^1.1.1", + "del": "^2.2.0", + "glob": "^7.0.3", + "ini": "^1.3.4", + "minimist": "^1.2.0", + "q": "^1.4.1", + "request": "^2.87.0", + "rimraf": "^2.5.2", + "semver": "^5.3.0", + "xml2js": "^0.4.17" + } + } + } + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "proxy-agent": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.0.3.tgz", + "integrity": "sha512-PXVVVuH9tiQuxQltFJVSnXWuDtNr+8aNBP6XVDDCDiUuDN8eRCm+ii4/mFWmXWEA0w8jjJSlePa4LXlM4jIzNA==", + "dev": true, + "optional": true, + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "pac-proxy-agent": "^3.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true, + "optional": true + } + } + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", + "dev": true, + "optional": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true, + "optional": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", + "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", + "dev": true + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "raw-loader": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", + "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", + "dev": true + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "dependencies": { + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "redis": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", + "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "dev": true, + "optional": true, + "requires": { + "double-ended-queue": "^2.1.0-0", + "redis-commands": "^1.2.0", + "redis-parser": "^2.6.0" + } + }, + "redis-commands": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz", + "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==", + "dev": true, + "optional": true + }, + "redis-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", + "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=", + "dev": true, + "optional": true + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "renderkid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.2.tgz", + "integrity": "sha512-FsygIxevi1jSiPY9h7vZmBFUbAOcbYm9UwyiLNdVsLRs/5We9Ob5NMPbGYUTWiLq5L+ezlVdE0A8bbME5CWTpg==", + "dev": true, + "requires": { + "css-select": "^1.1.0", + "dom-converter": "~0.2", + "htmlparser2": "~3.3.0", + "strip-ansi": "^3.0.0", + "utila": "^0.4.0" + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" + } + }, + "requestretry": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.13.0.tgz", + "integrity": "sha512-Lmh9qMvnQXADGAQxsXHP4rbgO6pffCfuR8XUBdP9aitJcLQJxhp7YZK4xAVYXnPJ5E52mwrfiKQtKonPL8xsmg==", + "dev": true, + "optional": true, + "requires": { + "extend": "^3.0.0", + "lodash": "^4.15.0", + "request": "^2.74.0", + "when": "^3.7.7" + }, + "dependencies": { + "when": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true, + "optional": true + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "requires": { + "symbol-observable": "1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "dev": true, + "optional": true, + "requires": { + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^7.0.0" + } + }, + "sass-loader": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.7.tgz", + "integrity": "sha512-JoiyD00Yo1o61OJsoP2s2kb19L1/Y2p3QFcCdWdF6oomBGKVYuZyqHWemRBfQ2uGYsk+CH3eCguXNfpjzlcpaA==", + "dev": true, + "requires": { + "clone-deep": "^2.0.1", + "loader-utils": "^1.0.1", + "lodash.tail": "^4.1.1", + "neo-async": "^2.5.0", + "pify": "^3.0.0" + } + }, + "saucelabs": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.3.0.tgz", + "integrity": "sha1-0kDoAJ33+ocwbsRXimm6O1xCT+4=", + "dev": true, + "requires": { + "https-proxy-agent": "^1.0.0" + }, + "dependencies": { + "agent-base": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "dev": true, + "requires": { + "extend": "~3.0.0", + "semver": "~5.0.1" + } + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "dev": true, + "requires": { + "agent-base": "2", + "debug": "2", + "extend": "3" + } + }, + "semver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=", + "dev": true + } + } + }, + "sax": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", + "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=", + "dev": true + }, + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "optional": true, + "requires": { + "js-base64": "^2.1.8", + "source-map": "^0.4.2" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selenium-webdriver": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.0.1.tgz", + "integrity": "sha1-ot6l2kqX9mcuiefKcnbO+jZRR6c=", + "dev": true, + "requires": { + "adm-zip": "^0.4.7", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "dependencies": { + "tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + } + } + }, + "selfsigned": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", + "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==", + "dev": true, + "requires": { + "node-forge": "0.7.5" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "semver-dsl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "semver-intersect": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", + "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", + "dev": true, + "requires": { + "semver": "^5.0.0" + } + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", + "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==", + "dev": true + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "dev": true, + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "silent-error": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/silent-error/-/silent-error-1.1.1.tgz", + "integrity": "sha512-n4iEKyNcg4v6/jpb3c0/iyH2G1nzUNl7Gpqtn/mHIJK9S/q/7MCfoO4rwVOoO59qPFIc0hVHvMbiOJ0NdtxKKw==", + "dev": true, + "requires": { + "debug": "^2.2.0" + } + }, + "slack-node": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/slack-node/-/slack-node-0.2.0.tgz", + "integrity": "sha1-3kuN3aqLeT9h29KTgQT9q/N9+jA=", + "dev": true, + "optional": true, + "requires": { + "requestretry": "^1.2.2" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "smart-buffer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", + "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==", + "dev": true + }, + "smtp-connection": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", + "dev": true, + "requires": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "optional": true, + "requires": { + "hoek": "2.x.x" + } + }, + "socket.io": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.0.4.tgz", + "integrity": "sha1-waRZDO/4fs8TxyZS8Eb3FrKeYBQ=", + "dev": true, + "requires": { + "debug": "~2.6.6", + "engine.io": "~3.1.0", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.0.4", + "socket.io-parser": "~3.1.1" + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.0.4.tgz", + "integrity": "sha1-CRilUkBtxeVAs4Dc2Xr8SmQzL44=", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~2.6.4", + "engine.io-client": "~3.1.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.1.1", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.1.3.tgz", + "integrity": "sha512-g0a2HPqLguqAczs3dMECuA1RgoGFPyvDqcbaDEdCWY9g59kdUAz3YRmaJBNKXflrHNwB7Q12Gkf/0CZXfdHR7g==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "has-binary2": "~1.0.2", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "dev": true, + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" + } + }, + "sockjs-client": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.5.tgz", + "integrity": "sha1-G7fA9yIsQPQq3xT0RCy9Eml3GoM=", + "dev": true, + "requires": { + "debug": "^2.6.6", + "eventsource": "0.1.6", + "faye-websocket": "~0.11.0", + "inherits": "^2.0.1", + "json3": "^3.3.2", + "url-parse": "^1.1.8" + }, + "dependencies": { + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + } + } + }, + "socks": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.3.tgz", + "integrity": "sha512-+2r83WaRT3PXYoO/1z+RDEBE7Z2f9YcdQnJ0K/ncXXbV5gJ6wYfNAebYFYiiUjM6E4JyXnPY8cimwyvFYHVUUA==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "4.0.2" + } + }, + "socks-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", + "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", + "dev": true, + "requires": { + "agent-base": "~4.2.0", + "socks": "~2.2.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", + "dev": true + }, + "spdy": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", + "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "dev": true, + "requires": { + "debug": "^2.6.8", + "handle-thing": "^1.2.5", + "http-deceiver": "^1.2.7", + "safe-buffer": "^5.0.1", + "select-hose": "^2.0.0", + "spdy-transport": "^2.0.18" + } + }, + "spdy-transport": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.1.tgz", + "integrity": "sha512-q7D8c148escoB3Z7ySCASadkegMmUZW8Wb/Q1u0/XBgDKMO880rLQDj8Twiew/tYi7ghemKUi/whSYOwE17f5Q==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "detect-node": "^2.0.3", + "hpack.js": "^2.1.6", + "obuf": "^1.1.1", + "readable-stream": "^2.2.9", + "safe-buffer": "^5.0.1", + "wbuf": "^1.7.2" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "optional": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "style-loader": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.19.1.tgz", + "integrity": "sha512-IRE+ijgojrygQi3rsqT0U4dd+UcPCqcVvauZpCnQrGAlEe+FUIyrK93bUDScamesjP08JlQNsFJU+KmPedP5Og==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^0.3.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "^5.0.0" + } + } + } + }, + "stylus": { + "version": "0.54.5", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz", + "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=", + "dev": true, + "requires": { + "css-parse": "1.7.x", + "debug": "*", + "glob": "7.0.x", + "mkdirp": "0.5.x", + "sax": "0.5.x", + "source-map": "0.1.x" + }, + "dependencies": { + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "stylus-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, + "tapable": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz", + "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==", + "dev": true + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "optional": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=", + "dev": true, + "optional": true + }, + "thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", + "dev": true + }, + "time-stamp": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.2.0.tgz", + "integrity": "sha512-zxke8goJQpBeEgD82CXABeMh0LSJcj7CXEd0OHOg45HgcofF7pxNwZm9+RknpxpDhwN4gFpySkApKfFYfRQnUA==", + "dev": true + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timespan": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/timespan/-/timespan-2.3.0.tgz", + "integrity": "sha1-SQLOBAvRPYRcj1myfp1ZutbzmSk=", + "dev": true, + "optional": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "optional": true, + "requires": { + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + } + } + }, + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.2" + } + }, + "ts-node": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-4.1.0.tgz", + "integrity": "sha512-xcZH12oVg9PShKhy3UHyDmuDLV3y7iKwX25aMVPt1SIXSuAfWkFiGPEkg+th8R4YKW/QCxDoW7lJdb15lx6QWg==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "chalk": "^2.3.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.0", + "tsconfig": "^7.0.0", + "v8flags": "^3.0.0", + "yn": "^2.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "requires": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "tsickle": { + "version": "0.27.5", + "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.27.5.tgz", + "integrity": "sha512-NP+CjM1EXza/M8mOXBLH3vkFEJiu1zfEAlC5WdJxHPn8l96QPz5eooP6uAgYtw1CcKfuSyIiheNUdKxtDWCNeg==", + "dev": true, + "requires": { + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map": "^0.6.0", + "source-map-support": "^0.5.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "tslint": { + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz", + "integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.12.1" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "dev": true, + "optional": true + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.3.tgz", + "integrity": "sha512-ptLSQs2S4QuS6/OD1eAKG+S5G8QQtrU5RT32JULdZQtM1L3WTi34Wsu48Yndzi8xsObRAB9RPt/KhA9wlpEF6w==", + "dev": true + }, + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "dev": true, + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", + "dev": true, + "requires": { + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "schema-utils": "^0.4.5", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "uglify-es": "^3.3.4", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "dev": true, + "requires": { + "commander": "~2.13.0", + "source-map": "~0.6.1" + } + } + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", + "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-loader": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.6.2.tgz", + "integrity": "sha512-h3qf9TNn53BpuXTTcpC+UehiRrl0Cv45Yr/xWayApjw6G8Bg2dGke7rIwDQ39piciWCWrC+WiqLjOh3SUp9n0Q==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "mime": "^1.4.1", + "schema-utils": "^0.3.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "^5.0.0" + } + } + } + }, + "url-parse": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", + "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", + "dev": true, + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "useragent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", + "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", + "dev": true, + "requires": { + "lru-cache": "2.2.x", + "tmp": "0.0.x" + }, + "dependencies": { + "lru-cache": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", + "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "dev": true + } + } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "uws": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/uws/-/uws-9.14.0.tgz", + "integrity": "sha512-HNMztPP5A1sKuVFmdZ6BPVpBQd5bUjNC8EFMFiICK+oho/OQsAJy5hnIx4btMHiOk8j04f/DbIlqnEZ9d72dqg==", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", + "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "vlq": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", + "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", + "dev": true + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webdriver-js-extender": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-1.0.0.tgz", + "integrity": "sha1-gcUzqeM9W/tZe05j4s2yW1R3dRU=", + "dev": true, + "requires": { + "@types/selenium-webdriver": "^2.53.35", + "selenium-webdriver": "^2.53.2" + }, + "dependencies": { + "adm-zip": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz", + "integrity": "sha1-ph7VrmkFw66lizplfSUDMJEFJzY=", + "dev": true + }, + "sax": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz", + "integrity": "sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk=", + "dev": true + }, + "selenium-webdriver": { + "version": "2.53.3", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz", + "integrity": "sha1-0p/1qVff8aG0ncRXdW5OS/vc4IU=", + "dev": true, + "requires": { + "adm-zip": "0.4.4", + "rimraf": "^2.2.8", + "tmp": "0.0.24", + "ws": "^1.0.1", + "xml2js": "0.4.4" + } + }, + "tmp": { + "version": "0.0.24", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz", + "integrity": "sha1-1qXhmNFKmDXMby18PZ4wJCjIzxI=", + "dev": true + }, + "ultron": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", + "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", + "dev": true + }, + "ws": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", + "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "dev": true, + "requires": { + "options": ">=0.0.5", + "ultron": "1.0.x" + } + }, + "xml2js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz", + "integrity": "sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0=", + "dev": true, + "requires": { + "sax": "0.6.x", + "xmlbuilder": ">=1.0.0" + } + } + } + }, + "webpack": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", + "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", + "dev": true, + "requires": { + "acorn": "^5.0.0", + "acorn-dynamic-import": "^2.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "async": "^2.1.2", + "enhanced-resolve": "^3.4.0", + "escope": "^3.6.0", + "interpret": "^1.0.0", + "json-loader": "^0.5.4", + "json5": "^0.5.1", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "mkdirp": "~0.5.0", + "node-libs-browser": "^2.0.0", + "source-map": "^0.5.3", + "supports-color": "^4.2.1", + "tapable": "^0.2.7", + "uglifyjs-webpack-plugin": "^0.4.6", + "watchpack": "^1.4.0", + "webpack-sources": "^1.0.1", + "yargs": "^8.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "^0.5.6", + "uglify-js": "^2.8.29", + "webpack-sources": "^1.0.1" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + } + } + }, + "webpack-dev-middleware": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "dev": true, + "requires": { + "memory-fs": "~0.4.1", + "mime": "^1.5.0", + "path-is-absolute": "^1.0.0", + "range-parser": "^1.0.3", + "time-stamp": "^2.0.0" + } + }, + "webpack-dev-server": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.3.tgz", + "integrity": "sha512-Qz22YEFhWx+M2vvJ+rQppRv39JA0h5NNbOOdODApdX6iZ52Diz7vTPXjF7kJlfn+Uc24Qr48I3SZ9yncQwRycg==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "array-includes": "^3.0.3", + "bonjour": "^3.5.0", + "chokidar": "^2.0.0", + "compression": "^1.5.2", + "connect-history-api-fallback": "^1.3.0", + "debug": "^3.1.0", + "del": "^3.0.0", + "express": "^4.16.2", + "html-entities": "^1.2.0", + "http-proxy-middleware": "~0.17.4", + "import-local": "^1.0.0", + "internal-ip": "1.2.0", + "ip": "^1.1.5", + "killable": "^1.0.0", + "loglevel": "^1.4.1", + "opn": "^5.1.0", + "portfinder": "^1.0.9", + "selfsigned": "^1.9.1", + "serve-index": "^1.7.2", + "sockjs": "0.3.19", + "sockjs-client": "1.1.5", + "spdy": "^3.4.1", + "strip-ansi": "^3.0.0", + "supports-color": "^5.1.0", + "webpack-dev-middleware": "1.12.2", + "yargs": "6.6.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^4.2.0" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + } + } + }, + "webpack-merge": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", + "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", + "dev": true, + "requires": { + "lodash": "^4.17.5" + } + }, + "webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webpack-subresource-integrity": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.3.2.tgz", + "integrity": "sha512-VpBtk0Ha1W0GebTzPj3Y8UqbmPDp+HqGlegRv+hS8g8/x818dw9NuEfJEOp5CF6zTPs3KF6aqknVu52Bh5h1eQ==", + "dev": true, + "requires": { + "webpack-sources": "^1.3.0" + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true + }, + "when": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", + "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "with-callback": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/with-callback/-/with-callback-1.0.2.tgz", + "integrity": "sha1-oJYpuakgAo1yFAT7Q1vc/1yRvCE=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + }, + "dependencies": { + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + } + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", + "dev": true, + "optional": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "xxhashjs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", + "dev": true, + "requires": { + "cuint": "^0.2.2" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "optional": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true, + "optional": true + } + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "^3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "optional": true + } + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + }, + "zone.js": { + "version": "0.8.29", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.29.tgz", + "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==" + } + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/package.json b/spring-boot-angular/src/main/java/com/baeldung/angularclient/package.json new file mode 100644 index 0000000000..a745cf671a --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/package.json @@ -0,0 +1,48 @@ +{ + "name": "sampleapp", + "version": "0.0.0", + "license": "MIT", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build --prod", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e" + }, + "private": true, + "dependencies": { + "@angular/animations": "^5.2.0", + "@angular/common": "^5.2.0", + "@angular/compiler": "^5.2.0", + "@angular/core": "^5.2.0", + "@angular/forms": "^5.2.0", + "@angular/http": "^5.2.0", + "@angular/platform-browser": "^5.2.0", + "@angular/platform-browser-dynamic": "^5.2.0", + "@angular/router": "^5.2.0", + "core-js": "^2.4.1", + "rxjs": "^5.5.6", + "zone.js": "^0.8.19" + }, + "devDependencies": { + "@angular/cli": "~1.7.4", + "@angular/compiler-cli": "^5.2.0", + "@angular/language-service": "^5.2.0", + "@types/jasmine": "~2.8.3", + "@types/jasminewd2": "~2.0.2", + "@types/node": "~6.0.60", + "codelyzer": "^4.0.1", + "jasmine-core": "~2.8.0", + "jasmine-spec-reporter": "~4.2.1", + "karma": "~2.0.0", + "karma-chrome-launcher": "~2.2.0", + "karma-coverage-istanbul-reporter": "^1.2.1", + "karma-jasmine": "~1.1.0", + "karma-jasmine-html-reporter": "^0.2.2", + "protractor": "~5.1.2", + "ts-node": "~4.1.0", + "tslint": "~5.9.1", + "typescript": "~2.5.3" + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/protractor.conf.js b/spring-boot-angular/src/main/java/com/baeldung/angularclient/protractor.conf.js new file mode 100644 index 0000000000..7ee3b5ee86 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/protractor.conf.js @@ -0,0 +1,28 @@ +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts + +const { SpecReporter } = require('jasmine-spec-reporter'); + +exports.config = { + allScriptsTimeout: 11000, + specs: [ + './e2e/**/*.e2e-spec.ts' + ], + capabilities: { + 'browserName': 'chrome' + }, + directConnect: true, + baseUrl: 'http://localhost:4200/', + framework: 'jasmine', + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + print: function() {} + }, + onPrepare() { + require('ts-node').register({ + project: 'e2e/tsconfig.e2e.json' + }); + jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + } +}; diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app-routing.module.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app-routing.module.ts new file mode 100644 index 0000000000..ecc848ac37 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app-routing.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { UserListComponent } from './user-list/user-list.component'; +import { UserFormComponent } from './user-form/user-form.component'; + +const routes: Routes = [ + { path: 'users', component: UserListComponent }, + { path: 'adduser', component: UserFormComponent } +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule { } diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.css b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.html b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.html new file mode 100644 index 0000000000..144a77ffe3 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.html @@ -0,0 +1,16 @@ +
+
+
+
+
+

{{ title }}

+ +
+
+ +
+
+
\ No newline at end of file diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.spec.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.spec.ts new file mode 100644 index 0000000000..e4ca195309 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.spec.ts @@ -0,0 +1,31 @@ +import { TestBed, async } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AppComponent } from './app.component'; +describe('AppComponent', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + RouterTestingModule + ], + declarations: [ + AppComponent + ], + }).compileComponents(); + })); + it('should create the app', async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app).toBeTruthy(); + })); + it(`should have as title 'app'`, async(() => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.debugElement.componentInstance; + expect(app.title).toEqual('app'); + })); + it('should render title in a h1 tag', async(() => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!'); + })); +}); diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.ts new file mode 100644 index 0000000000..b14112f90b --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +export class AppComponent { + + title: string; + + constructor() { + this.title = 'Spring Boot - Angular Application'; + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.module.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.module.ts new file mode 100644 index 0000000000..3c6c070d96 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.module.ts @@ -0,0 +1,26 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { AppRoutingModule } from './app-routing.module'; +import { FormsModule } from '@angular/forms'; +import { HttpClientModule } from '@angular/common/http'; +import { AppComponent } from './app.component'; +import { UserListComponent } from './user-list/user-list.component'; +import { UserFormComponent } from './user-form/user-form.component'; +import { UserService } from './service/user.service'; + +@NgModule({ + declarations: [ + AppComponent, + UserListComponent, + UserFormComponent + ], + imports: [ + BrowserModule, + AppRoutingModule, + HttpClientModule, + FormsModule + ], + providers: [UserService], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/model/user.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/model/user.ts new file mode 100644 index 0000000000..f78cda4bf9 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/model/user.ts @@ -0,0 +1,5 @@ +export class User { + id: string; + name: string; + email: string; +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.spec.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.spec.ts new file mode 100644 index 0000000000..b26195c25d --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.spec.ts @@ -0,0 +1,15 @@ +import { TestBed, inject } from '@angular/core/testing'; + +import { UserService } from './user.service'; + +describe('UserService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [UserService] + }); + }); + + it('should be created', inject([UserService], (service: UserService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.ts new file mode 100644 index 0000000000..e587632017 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { User } from '../model/user'; +import { Observable } from 'rxjs/Observable'; + +@Injectable() +export class UserService { + + private usersUrl: string; + + constructor(private http: HttpClient) { + this.usersUrl = 'http://localhost:8080/users'; + } + + public findAll(): Observable { + return this.http.get(this.usersUrl); + } + + public save(user: User) { + return this.http.post(this.usersUrl, user); + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.css b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.html b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.html new file mode 100644 index 0000000000..7cf1800e50 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.html @@ -0,0 +1,19 @@ +
+
+
+
+ + +
+
Name is required
+
+ + +
Email is required
+
+ +
+
+
\ No newline at end of file diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.spec.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.spec.ts new file mode 100644 index 0000000000..9e613476f5 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserFormComponent } from './user-form.component'; + +describe('UserFormComponent', () => { + let component: UserFormComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ UserFormComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(UserFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.ts new file mode 100644 index 0000000000..869d53aede --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.ts @@ -0,0 +1,26 @@ +import { Component } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { UserService } from '../service/user.service'; +import { User } from '../model/user'; + +@Component({ + selector: 'app-user-form', + templateUrl: './user-form.component.html', + styleUrls: ['./user-form.component.css'] +}) +export class UserFormComponent { + + user: User; + + constructor(private route: ActivatedRoute, private router: Router, private userService: UserService) { + this.user = new User(); + } + + onSubmit() { + this.userService.save(this.user).subscribe(result => this.gotoUserList()); + } + + gotoUserList() { + this.router.navigate(['/users']); + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.css b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.html b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.html new file mode 100644 index 0000000000..1ac849f552 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.html @@ -0,0 +1,20 @@ +
+
+ + + + + + + + + + + + + + + +
#NameEmail
{{ user.id }}{{ user.name }}{{ user.email }}
+
+
\ No newline at end of file diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.spec.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.spec.ts new file mode 100644 index 0000000000..9d521807d6 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { UserListComponent } from './user-list.component'; + +describe('UserListComponent', () => { + let component: UserListComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ UserListComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(UserListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.ts new file mode 100644 index 0000000000..91226695f5 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.ts @@ -0,0 +1,23 @@ +import { Component, OnInit } from '@angular/core'; +import { User } from '../model/user'; +import { UserService } from '../service/user.service'; + +@Component({ + selector: 'app-user-list', + templateUrl: './user-list.component.html', + styleUrls: ['./user-list.component.css'] +}) +export class UserListComponent implements OnInit { + + users: User[]; + + constructor(private userService: UserService) { + + } + + ngOnInit() { + this.userService.findAll().subscribe(data => { + this.users = data; + }); + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/assets/.gitkeep b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.prod.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.prod.ts new file mode 100644 index 0000000000..3612073bc3 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.prod.ts @@ -0,0 +1,3 @@ +export const environment = { + production: true +}; diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.ts new file mode 100644 index 0000000000..b7f639aeca --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.ts @@ -0,0 +1,8 @@ +// The file contents for the current environment will overwrite these during build. +// The build system defaults to the dev environment which uses `environment.ts`, but if you do +// `ng build --env=prod` then `environment.prod.ts` will be used instead. +// The list of which env maps to which file can be found in `.angular-cli.json`. + +export const environment = { + production: false +}; diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/favicon.ico b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8081c7ceaf2be08bf59010158c586170d9d2d517 GIT binary patch literal 5430 zcmc(je{54#6vvCoAI3i*G5%$U7!sA3wtMZ$fH6V9C`=eXGJb@R1%(I_{vnZtpD{6n z5Pl{DmxzBDbrB>}`90e12m8T*36WoeDLA&SD_hw{H^wM!cl_RWcVA!I+x87ee975; z@4kD^=bYPn&pmG@(+JZ`rqQEKxW<}RzhW}I!|ulN=fmjVi@x{p$cC`)5$a!)X&U+blKNvN5tg=uLvuLnuqRM;Yc*swiexsoh#XPNu{9F#c`G zQLe{yWA(Y6(;>y|-efAy11k<09(@Oo1B2@0`PtZSkqK&${ zgEY}`W@t{%?9u5rF?}Y7OL{338l*JY#P!%MVQY@oqnItpZ}?s z!r?*kwuR{A@jg2Chlf0^{q*>8n5Ir~YWf*wmsh7B5&EpHfd5@xVaj&gqsdui^spyL zB|kUoblGoO7G(MuKTfa9?pGH0@QP^b#!lM1yHWLh*2iq#`C1TdrnO-d#?Oh@XV2HK zKA{`eo{--^K&MW66Lgsktfvn#cCAc*(}qsfhrvOjMGLE?`dHVipu1J3Kgr%g?cNa8 z)pkmC8DGH~fG+dlrp(5^-QBeEvkOvv#q7MBVLtm2oD^$lJZx--_=K&Ttd=-krx(Bb zcEoKJda@S!%%@`P-##$>*u%T*mh+QjV@)Qa=Mk1?#zLk+M4tIt%}wagT{5J%!tXAE;r{@=bb%nNVxvI+C+$t?!VJ@0d@HIyMJTI{vEw0Ul ze(ha!e&qANbTL1ZneNl45t=#Ot??C0MHjjgY8%*mGisN|S6%g3;Hlx#fMNcL<87MW zZ>6moo1YD?P!fJ#Jb(4)_cc50X5n0KoDYfdPoL^iV`k&o{LPyaoqMqk92wVM#_O0l z09$(A-D+gVIlq4TA&{1T@BsUH`Bm=r#l$Z51J-U&F32+hfUP-iLo=jg7Xmy+WLq6_tWv&`wDlz#`&)Jp~iQf zZP)tu>}pIIJKuw+$&t}GQuqMd%Z>0?t%&BM&Wo^4P^Y z)c6h^f2R>X8*}q|bblAF?@;%?2>$y+cMQbN{X$)^R>vtNq_5AB|0N5U*d^T?X9{xQnJYeU{ zoZL#obI;~Pp95f1`%X3D$Mh*4^?O?IT~7HqlWguezmg?Ybq|7>qQ(@pPHbE9V?f|( z+0xo!#m@Np9PljsyxBY-UA*{U*la#8Wz2sO|48_-5t8%_!n?S$zlGe+NA%?vmxjS- zHE5O3ZarU=X}$7>;Okp(UWXJxI%G_J-@IH;%5#Rt$(WUX?6*Ux!IRd$dLP6+SmPn= z8zjm4jGjN772R{FGkXwcNv8GBcZI#@Y2m{RNF_w8(Z%^A*!bS*!}s6sh*NnURytky humW;*g7R+&|Ledvc- + + + + + Spring Boot - Angular Application + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/main.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/main.ts new file mode 100644 index 0000000000..91ec6da5f0 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.log(err)); diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/polyfills.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/polyfills.ts new file mode 100644 index 0000000000..af84770782 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/polyfills.ts @@ -0,0 +1,79 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE9, IE10 and IE11 requires all of the following polyfills. **/ +// import 'core-js/es6/symbol'; +// import 'core-js/es6/object'; +// import 'core-js/es6/function'; +// import 'core-js/es6/parse-int'; +// import 'core-js/es6/parse-float'; +// import 'core-js/es6/number'; +// import 'core-js/es6/math'; +// import 'core-js/es6/string'; +// import 'core-js/es6/date'; +// import 'core-js/es6/array'; +// import 'core-js/es6/regexp'; +// import 'core-js/es6/map'; +// import 'core-js/es6/weak-map'; +// import 'core-js/es6/set'; + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** IE10 and IE11 requires the following for the Reflect API. */ +// import 'core-js/es6/reflect'; + + +/** Evergreen browsers require these. **/ +// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. +import 'core-js/es7/reflect'; + + +/** + * Required to support Web Animations `@angular/platform-browser/animations`. + * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation + **/ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + */ + + // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + + /* + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + */ +// (window as any).__Zone_enable_cross_context_check = true; + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + + + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/styles.css b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/styles.css new file mode 100644 index 0000000000..90d4ee0072 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/styles.css @@ -0,0 +1 @@ +/* You can add global styles to this file, and also import other style files */ diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.app.json b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.app.json new file mode 100644 index 0000000000..39ba8dbacb --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.app.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/app", + "baseUrl": "./", + "module": "es2015", + "types": [] + }, + "exclude": [ + "test.ts", + "**/*.spec.ts" + ] +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.spec.json b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.spec.json new file mode 100644 index 0000000000..ac22a298ac --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.spec.json @@ -0,0 +1,19 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/spec", + "baseUrl": "./", + "module": "commonjs", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/typings.d.ts b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/typings.d.ts new file mode 100644 index 0000000000..ef5c7bd620 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/typings.d.ts @@ -0,0 +1,5 @@ +/* SystemJS module definition */ +declare var module: NodeModule; +interface NodeModule { + id: string; +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/tsconfig.json b/spring-boot-angular/src/main/java/com/baeldung/angularclient/tsconfig.json new file mode 100644 index 0000000000..a6c016bf38 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es5", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2017", + "dom" + ] + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/tslint.json b/spring-boot-angular/src/main/java/com/baeldung/angularclient/tslint.json new file mode 100644 index 0000000000..9963d6c395 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/angularclient/tslint.json @@ -0,0 +1,143 @@ +{ + "rulesDirectory": [ + "node_modules/codelyzer" + ], + "rules": { + "arrow-return-shorthand": true, + "callable-types": true, + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "deprecation": { + "severity": "warn" + }, + "eofline": true, + "forin": true, + "import-blacklist": [ + true, + "rxjs", + "rxjs/Rx" + ], + "import-spacing": true, + "indent": [ + true, + "spaces" + ], + "interface-over-type-literal": true, + "label-position": true, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-super": true, + "no-empty": false, + "no-empty-interface": true, + "no-eval": true, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-misused-new": true, + "no-non-null-assertion": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-string-throw": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unnecessary-initializer": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "prefer-const": true, + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": [ + true, + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "unified-signatures": true, + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ], + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ], + "no-output-on-prefix": true, + "use-input-property-decorator": true, + "use-output-property-decorator": true, + "use-host-property-decorator": true, + "no-input-rename": true, + "no-output-rename": true, + "use-life-cycle-interface": true, + "use-pipe-transform-interface": true, + "component-class-suffix": true, + "directive-class-suffix": true + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/application/Application.java b/spring-boot-angular/src/main/java/com/baeldung/application/Application.java new file mode 100644 index 0000000000..f1155c3106 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/application/Application.java @@ -0,0 +1,28 @@ +package com.baeldung.application; + +import com.baeldung.application.entities.User; +import com.baeldung.application.repositories.UserRepository; +import java.util.stream.Stream; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + CommandLineRunner init(UserRepository userRepository) { + return args -> { + Stream.of("John", "Julie", "Jennifer", "Helen", "Rachel").forEach(name -> { + User user = new User(name, name.toLowerCase() + "@domain.com"); + userRepository.save(user); + }); + userRepository.findAll().forEach(System.out::println); + }; + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/application/controllers/UserController.java b/spring-boot-angular/src/main/java/com/baeldung/application/controllers/UserController.java new file mode 100644 index 0000000000..c101ed771f --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/application/controllers/UserController.java @@ -0,0 +1,31 @@ +package com.baeldung.application.controllers; + +import com.application.entities.User; +import com.baeldung.application.repositories.UserRepository; +import java.util.List; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@CrossOrigin(origins = "http://localhost:4200") +public class UserController { + + private final UserRepository userRepository; + + public UserController(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @GetMapping("/users") + public List getUsers() { + return (List) userRepository.findAll(); + } + + @PostMapping("/users") + void addUser(@RequestBody User user) { + userRepository.save(user); + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/application/entities/User.java b/spring-boot-angular/src/main/java/com/baeldung/application/entities/User.java new file mode 100644 index 0000000000..4c346fa5b9 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/application/entities/User.java @@ -0,0 +1,43 @@ +package com.baeldung.application.entities; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + private final String name; + private final String email; + + public User() { + this.name = ""; + this.email = ""; + } + + public User(String name, String email) { + this.name = name; + this.email = email; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + @Override + public String toString() { + return "User{" + "id=" + id + ", name=" + name + ", email=" + email + '}'; + } +} diff --git a/spring-boot-angular/src/main/java/com/baeldung/application/repositories/UserRepository.java b/spring-boot-angular/src/main/java/com/baeldung/application/repositories/UserRepository.java new file mode 100644 index 0000000000..f8ef5a4c0c --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/application/repositories/UserRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.application.repositories; + +import com.baeldung.application.entities.User; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; +import org.springframework.web.bind.annotation.CrossOrigin; + +@Repository +@CrossOrigin(origins = "http://localhost:4200") +public interface UserRepository extends CrudRepository{} From 6bae0fc28aa6209a760832888baf5cfa9cdc6324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C4=B1v=C4=B1lc=C4=B1m?= Date: Tue, 26 Feb 2019 07:04:16 +0300 Subject: [PATCH 115/496] BAEL-2583 JUnit 5: Conditional Test Execution (#6302) * BAEL-2583 JUnit 5: Conditional Test Execution * BAEL-2583 conditional test annotation classes methods extended with printline comments --- .../ConditionalAnnotationsUnitTest.java | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 testing-modules/junit-5/src/test/java/com/baeldung/conditional/ConditionalAnnotationsUnitTest.java diff --git a/testing-modules/junit-5/src/test/java/com/baeldung/conditional/ConditionalAnnotationsUnitTest.java b/testing-modules/junit-5/src/test/java/com/baeldung/conditional/ConditionalAnnotationsUnitTest.java new file mode 100644 index 0000000000..ec76bd1488 --- /dev/null +++ b/testing-modules/junit-5/src/test/java/com/baeldung/conditional/ConditionalAnnotationsUnitTest.java @@ -0,0 +1,119 @@ +package com.baeldung.conditional; + +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.*; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +public class ConditionalAnnotationsUnitTest { + @Test + @EnabledOnOs({OS.WINDOWS, OS.MAC}) + public void shouldRunBothWindowsAndMac() { + System.out.println("runs on Windows and Mac"); + } + + @Test + @DisabledOnOs(OS.LINUX) + public void shouldNotRunAtLinux() { + System.out.println("will not run on Linux"); + } + + @Test + @EnabledOnJre({JRE.JAVA_10, JRE.JAVA_11}) + public void shouldOnlyRunOnJava10And11() { + System.out.println("runs with java 10 and 11"); + } + + @Test + @DisabledOnJre(JRE.OTHER) + public void thisTestOnlyRunsWithUpToDateJREs() { + System.out.println("this test will only run on java8, 9, 10 and 11."); + } + + @Test + @EnabledIfSystemProperty(named = "java.vm.vendor", matches = "Oracle.*") + public void onlyIfVendorNameStartsWithOracle() { + System.out.println("runs only if vendor name starts with Oracle"); + } + + @Test + @DisabledIfSystemProperty(named = "file.separator", matches = "[/]") + public void disabledIfFileSeperatorIsSlash() { + System.out.println("Will not run if file.sepeartor property is /"); + } + + @Test + @EnabledIfEnvironmentVariable(named = "GDMSESSION", matches = "ubuntu") + public void onlyRunOnUbuntuServer() { + System.out.println("only runs if GDMSESSION is ubuntu"); + } + + @Test + @DisabledIfEnvironmentVariable(named = "LC_TIME", matches = ".*UTF-8.") + public void shouldNotRunWhenTimeIsNotUTF8() { + System.out.println("will not run if environment variable LC_TIME is UTF-8"); + } + + @Test + @EnabledIf("'FR' == systemProperty.get('user.country')") + public void onlyFrenchPeopleWillRunThisMethod() { + System.out.println("will run only if user.country is FR"); + } + + @Test + @DisabledIf("java.lang.System.getProperty('os.name').toLowerCase().contains('mac')") + public void shouldNotRunOnMacOS() { + System.out.println("will not run if our os.name is mac"); + } + + @Test + @EnabledIf(value = { + "load('nashorn:mozilla_compat.js')", + "importPackage(java.time)", + "", + "var thisMonth = LocalDate.now().getMonth().name()", + "var february = Month.FEBRUARY.name()", + "thisMonth.equals(february)" + }, + engine = "nashorn", + reason = "Self-fulfilling: {result}") + public void onlyRunsInFebruary() { + System.out.println("this test only runs in February"); + } + + @Test + @DisabledIf("systemEnvironment.get('XPC_SERVICE_NAME') != null " + + "&& systemEnvironment.get('XPC_SERVICE_NAME').contains('intellij')") + public void notValidForIntelliJ() { + System.out.println("this test will run if our ide is INTELLIJ"); + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @Test + @DisabledOnOs({OS.WINDOWS, OS.SOLARIS, OS.OTHER}) + @EnabledOnJre({JRE.JAVA_9, JRE.JAVA_10, JRE.JAVA_11}) + @interface ThisTestWillOnlyRunAtLinuxAndMacWithJava9Or10Or11 { + } + + @ThisTestWillOnlyRunAtLinuxAndMacWithJava9Or10Or11 + public void someSuperTestMethodHere() { + System.out.println("this method will run with java9, 10, 11 and Linux or macOS."); + } + + @Target(ElementType.METHOD) + @Retention(RetentionPolicy.RUNTIME) + @DisabledIf("Math.random() >= 0.5") + @interface CoinToss { + } + + @RepeatedTest(2) + @CoinToss + public void gamble() { + System.out.println("This tests run status is a gamble with %50 rate"); + } +} From 4be7eaf4198fbb348fb6bc3a514b67349565be8f Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Tue, 26 Feb 2019 17:52:54 +0530 Subject: [PATCH 116/496] BAEL-10944 Added logic of returning fixed date time zone in HelloResource --- restx/src/main/java/restx/demo/rest/HelloResource.java | 6 ++++-- .../resources/specs/hello/should_admin_say_hello.spec.yaml | 2 +- .../resources/specs/hello/should_anyone_say_hello.spec.yaml | 2 +- .../resources/specs/hello/should_user1_say_hello.spec.yaml | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/restx/src/main/java/restx/demo/rest/HelloResource.java b/restx/src/main/java/restx/demo/rest/HelloResource.java index 5cb2c2a5e6..115212ddf9 100644 --- a/restx/src/main/java/restx/demo/rest/HelloResource.java +++ b/restx/src/main/java/restx/demo/rest/HelloResource.java @@ -3,6 +3,8 @@ package restx.demo.rest; import restx.demo.domain.Message; import restx.demo.Roles; import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; + import restx.annotations.GET; import restx.annotations.POST; import restx.annotations.RestxResource; @@ -29,7 +31,7 @@ public class HelloResource { return new Message().setMessage(String.format( "hello %s, it's %s", RestxSession.current().getPrincipal().get().getName(), - DateTime.now().toString("HH:mm:ss"))); + DateTime.now(DateTimeZone.UTC).toString("HH:mm:ss"))); } /** @@ -44,7 +46,7 @@ public class HelloResource { public Message helloPublic(String who) { return new Message().setMessage(String.format( "hello %s, it's %s", - who, DateTime.now().toString("HH:mm:ss"))); + who, DateTime.now(DateTimeZone.UTC).toString("HH:mm:ss"))); } public static class MyPOJO { diff --git a/restx/src/test/resources/specs/hello/should_admin_say_hello.spec.yaml b/restx/src/test/resources/specs/hello/should_admin_say_hello.spec.yaml index f50059903f..7a8bd9119f 100644 --- a/restx/src/test/resources/specs/hello/should_admin_say_hello.spec.yaml +++ b/restx/src/test/resources/specs/hello/should_admin_say_hello.spec.yaml @@ -7,4 +7,4 @@ wts: GET message $RestxSession: {"_expires":"2013-09-27T01:18:00.822+02:00","principal":"admin","sessionKey":"e2b4430f-9541-4602-9a3a-413d17c56a6b"} then: | - {"message":"hello admin, it's 04:48:00"} + {"message":"hello admin, it's 23:18:00"} diff --git a/restx/src/test/resources/specs/hello/should_anyone_say_hello.spec.yaml b/restx/src/test/resources/specs/hello/should_anyone_say_hello.spec.yaml index 4b84cee9f4..d23e5ae6bf 100644 --- a/restx/src/test/resources/specs/hello/should_anyone_say_hello.spec.yaml +++ b/restx/src/test/resources/specs/hello/should_anyone_say_hello.spec.yaml @@ -5,4 +5,4 @@ wts: - when: | GET hello?who=xavier then: | - {"message":"hello xavier, it's 04:48:00"} + {"message":"hello xavier, it's 23:18:00"} diff --git a/restx/src/test/resources/specs/hello/should_user1_say_hello.spec.yaml b/restx/src/test/resources/specs/hello/should_user1_say_hello.spec.yaml index 825d1bb1b3..2db8a01003 100644 --- a/restx/src/test/resources/specs/hello/should_user1_say_hello.spec.yaml +++ b/restx/src/test/resources/specs/hello/should_user1_say_hello.spec.yaml @@ -7,4 +7,4 @@ wts: GET message $RestxSession: {"_expires":"2013-09-27T01:18:00.822+02:00","principal":"user1","sessionKey":"e2b4430f-9541-4602-9a3a-413d17c56a6b"} then: | - {"message":"hello user1, it's 04:48:00"} + {"message":"hello user1, it's 23:18:00"} From 687c2862b119c9b3f5c9e7a98ad339d5cad50f9a Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Tue, 26 Feb 2019 20:37:51 +0530 Subject: [PATCH 117/496] BAEL-10943 Removed unnecessary repositories --- geotools/pom.xml | 13 ------------- pom.xml | 4 ++-- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/geotools/pom.xml b/geotools/pom.xml index f2a9a77d2a..17beded326 100644 --- a/geotools/pom.xml +++ b/geotools/pom.xml @@ -33,24 +33,11 @@ - - maven2-repository.dev.java.net - Java.net repository - http://download.java.net/maven/2 - osgeo Open Source Geospatial Foundation Repository http://download.osgeo.org/webdav/geotools/ - - - true - - opengeo - OpenGeo Maven Repository - http://repo.opengeo.org - diff --git a/pom.xml b/pom.xml index 4625f8e6e8..103eaf5298 100644 --- a/pom.xml +++ b/pom.xml @@ -412,7 +412,7 @@ feign flyway-cdi-extension - + geotools google-cloud google-web-toolkit @@ -1130,7 +1130,7 @@ feign flyway-cdi-extension - + geotools google-cloud google-web-toolkit From b375c4a70c9352dd8a18da87c22fb6b3cf6da037 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Tue, 26 Feb 2019 20:48:24 +0530 Subject: [PATCH 118/496] BAEL-12771 Removed spring milestore repos --- .../etl/customer-mongodb-sink/pom.xml | 11 ----------- spring-cloud-data-flow/etl/customer-transform/pom.xml | 11 ----------- spring-cloud/spring-cloud-vault/pom.xml | 11 ----------- spring-zuul/pom.xml | 11 ----------- 4 files changed, 44 deletions(-) diff --git a/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml b/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml index c8b609fd70..369247f370 100644 --- a/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml +++ b/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml @@ -60,17 +60,6 @@
- - - spring-milestones - Spring Milestones - http://repo.spring.io/milestone - - false - - - - UTF-8 UTF-8 diff --git a/spring-cloud-data-flow/etl/customer-transform/pom.xml b/spring-cloud-data-flow/etl/customer-transform/pom.xml index 5b2eb05fc8..2b650c80bb 100644 --- a/spring-cloud-data-flow/etl/customer-transform/pom.xml +++ b/spring-cloud-data-flow/etl/customer-transform/pom.xml @@ -52,17 +52,6 @@ - - - spring-milestones - Spring Milestones - http://repo.spring.io/milestone - - false - - - - UTF-8 UTF-8 diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml index abfb0d06f3..766dfa10c7 100644 --- a/spring-cloud/spring-cloud-vault/pom.xml +++ b/spring-cloud/spring-cloud-vault/pom.xml @@ -65,17 +65,6 @@ - - - spring-milestones - Spring Milestones - http://repo.spring.io/milestone - - false - - - - UTF-8 UTF-8 diff --git a/spring-zuul/pom.xml b/spring-zuul/pom.xml index d00a932168..c26c75cf07 100644 --- a/spring-zuul/pom.xml +++ b/spring-zuul/pom.xml @@ -45,15 +45,4 @@ 2.6 - - - spring-milestones - Spring Milestones - http://repo.spring.io/milestone - - false - - - - \ No newline at end of file From 34803f7aa00585e05ffbb38685ee9fef911ea3a5 Mon Sep 17 00:00:00 2001 From: Krzysztof Majewski Date: Tue, 26 Feb 2019 17:10:43 +0100 Subject: [PATCH 119/496] BAEL-2576 - add ControllerAdvice --- .../ConstraintViolationExceptionHandler.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java new file mode 100644 index 0000000000..645b36c2a5 --- /dev/null +++ b/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java @@ -0,0 +1,21 @@ +package com.baeldung.spring.controller; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +import javax.validation.ConstraintViolationException; + +@ControllerAdvice +public class ConstraintViolationExceptionHandler extends ResponseEntityExceptionHandler { + + @ExceptionHandler(value = {ConstraintViolationException.class}) + protected ResponseEntity handleConstraintViolation(ConstraintViolationException e, WebRequest request) { + return handleExceptionInternal(e, e.getMessage(), new HttpHeaders(), HttpStatus.BAD_REQUEST, request); + } +} + From 31155f180df71a542e96cf016cdda7f5cff53f60 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Tue, 26 Feb 2019 22:41:32 +0200 Subject: [PATCH 120/496] Update pom.xml --- restx/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/restx/pom.xml b/restx/pom.xml index 16d785956a..49c0650326 100644 --- a/restx/pom.xml +++ b/restx/pom.xml @@ -151,6 +151,6 @@ 1.8 1.8 0.35-rc4 - 1.2.3 + 1.2.3 From b8411e44a3ca93797eaf2d15a4a8c3884a6f7939 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Wed, 27 Feb 2019 15:33:20 +0800 Subject: [PATCH 121/496] Update README.md --- spring-rest-full/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index 32b65ccc6a..ed6df1675f 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -12,7 +12,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [Project Configuration with Spring](http://www.baeldung.com/project-configuration-with-spring) - [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics) -- [Bootstrap a Web Application with Spring 4](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) +- [Bootstrap a Web Application with Spring 5](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) - [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic) From dbb7b45460e7e1f60b909e37a6b28561ede9d523 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Wed, 27 Feb 2019 16:17:25 +0800 Subject: [PATCH 122/496] Update README.md --- aws/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/aws/README.md b/aws/README.md index 2c61928095..d14ea8a75e 100644 --- a/aws/README.md +++ b/aws/README.md @@ -4,7 +4,6 @@ - [AWS S3 with Java](http://www.baeldung.com/aws-s3-java) - [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda) - [Managing EC2 Instances in Java](http://www.baeldung.com/ec2-java) -- [http://www.baeldung.com/aws-s3-multipart-upload](https://github.com/eugenp/tutorials/tree/master/aws) - [Multipart Uploads in Amazon S3 with Java](http://www.baeldung.com/aws-s3-multipart-upload) - [Integration Testing with a Local DynamoDB Instance](http://www.baeldung.com/dynamodb-local-integration-tests) - [Using the JetS3t Java Client With Amazon S3](http://www.baeldung.com/jets3t-amazon-s3) From e60c69198eb27ca097894ac5cb3b2d143e139480 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Wed, 27 Feb 2019 16:46:15 +0800 Subject: [PATCH 123/496] Update README.md --- core-java-9/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-9/README.md b/core-java-9/README.md index d9586ba684..904782819c 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -16,7 +16,7 @@ - [Java 9 Reactive Streams](http://www.baeldung.com/java-9-reactive-streams) - [Java 9 java.util.Objects Additions](http://www.baeldung.com/java-9-objects-new) - [Java 9 Variable Handles Demistyfied](http://www.baeldung.com/java-variable-handles) -- [Exploring the New HTTP Client in Java 9](http://www.baeldung.com/java-9-http-client) +- [Exploring the New HTTP Client in Java 9 and 11](http://www.baeldung.com/java-9-http-client) - [Method Handles in Java](http://www.baeldung.com/java-method-handles) - [Introduction to Chronicle Queue](http://www.baeldung.com/java-chronicle-queue) - [A Guide to Java 9 Modularity](http://www.baeldung.com/java-9-modularity) From 3fe623dcabeba47b36fe5d50b7c1ff21ece4afe9 Mon Sep 17 00:00:00 2001 From: PranayJain Date: Wed, 27 Feb 2019 15:00:02 +0530 Subject: [PATCH 124/496] BAEL-2719: Spring Boot - Properties file outside jar --- .../ExternalPropertyFileLoader.java | 17 +++++++++++++ .../main/resources/external/conf.properties | 4 +++ .../ExternalPropertyFileLoaderUnitTest.java | 25 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyFileLoader.java create mode 100644 spring-boot-ops/src/main/resources/external/conf.properties create mode 100644 spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderUnitTest.java diff --git a/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyFileLoader.java b/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyFileLoader.java new file mode 100644 index 0000000000..233ddc0195 --- /dev/null +++ b/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyFileLoader.java @@ -0,0 +1,17 @@ +package com.baeldung.properties; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; + +@SpringBootApplication +public class ExternalPropertyFileLoader { + public static void main(String[] args) { + ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ExternalPropertyFileLoader.class).properties("spring.config.name:conf", "spring.config.location:file:src/main/resources/external/") + .build() + .run(args); + ConfigurableEnvironment environment = applicationContext.getEnvironment(); + environment.getProperty("username"); + } +} diff --git a/spring-boot-ops/src/main/resources/external/conf.properties b/spring-boot-ops/src/main/resources/external/conf.properties new file mode 100644 index 0000000000..a724b878b4 --- /dev/null +++ b/spring-boot-ops/src/main/resources/external/conf.properties @@ -0,0 +1,4 @@ +url=jdbc:postgresql://localhost:5432/ +username=admin +password=root +spring.main.allow-bean-definition-overriding=true diff --git a/spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderUnitTest.java b/spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderUnitTest.java new file mode 100644 index 0000000000..656d8561ec --- /dev/null +++ b/spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.properties; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +public class ExternalPropertyFileLoaderUnitTest { + + @Test + public void whenExternalisedPropertiesLoaded_thenReadValues() { + ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ExternalPropertyFileLoader.class).properties("spring.config.name:conf", "spring.config.location:file:src/main/resources/external/") + .build() + .run(); + ConfigurableEnvironment environment = applicationContext.getEnvironment(); + Assert.assertEquals(environment.getProperty("url"), "jdbc:postgresql://localhost:5432/"); + Assert.assertEquals(environment.getProperty("username"), "admin"); + Assert.assertEquals(environment.getProperty("password"), "root"); + } + +} From b293765466f81770236425bf2f0b4b7b78b10fb5 Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Wed, 27 Feb 2019 10:46:07 -0300 Subject: [PATCH 125/496] Guide to Stream.reduce() (#6425) * Initial Commit * Update Application.java --- .../reduce/application/Application.java | 70 ++++++++++++++++ .../com/baeldung/reduce/entities/User.java | 25 ++++++ .../reduce/utilities/NumberUtils.java | 52 ++++++++++++ .../reduce/tests/StreamReduceUnitTest.java | 79 +++++++++++++++++++ 4 files changed, 226 insertions(+) create mode 100644 java-streams/src/main/java/com/baeldung/reduce/application/Application.java create mode 100644 java-streams/src/main/java/com/baeldung/reduce/entities/User.java create mode 100644 java-streams/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java create mode 100644 java-streams/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java diff --git a/java-streams/src/main/java/com/baeldung/reduce/application/Application.java b/java-streams/src/main/java/com/baeldung/reduce/application/Application.java new file mode 100644 index 0000000000..b101c86780 --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/reduce/application/Application.java @@ -0,0 +1,70 @@ +package com.baeldung.reduce.application; + +import com.baeldung.reduce.entities.User; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Warmup; + +public class Application { + + public static void main(String[] args) throws Exception { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result1 = numbers.stream().reduce(0, (subtotal, element) -> subtotal + element); + System.out.println(result1); + + int result2 = numbers.stream().reduce(0, Integer::sum); + System.out.println(result2); + + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result3 = letters.stream().reduce("", (partialString, element) -> partialString + element); + System.out.println(result3); + + String result4 = letters.stream().reduce("", String::concat); + System.out.println(result4); + + String result5 = letters.stream().reduce("", (partialString, element) -> partialString.toUpperCase() + element.toUpperCase()); + System.out.println(result5); + + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + int result6 = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result6); + + String result7 = letters.parallelStream().reduce("", String::concat); + System.out.println(result7); + + int result8 = users.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result8); + + org.openjdk.jmh.Main.main(args); + + } + + @Benchmark + @Fork(value = 1, warmups = 2) + @Warmup(iterations = 2) + @BenchmarkMode(Mode.AverageTime) + public void executeReduceOnParallelizedStream() { + List userList = new ArrayList<>(); + for (int i = 0; i <= 1000000; i++) { + userList.add(new User("John" + i, i)); + } + userList.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + } + + @Benchmark + @Fork(value = 1, warmups = 2) + @Warmup(iterations = 2) + @BenchmarkMode(Mode.AverageTime) + public void executeReduceOnSequentialStream() { + List userList = new ArrayList<>(); + for (int i = 0; i <= 1000000; i++) { + userList.add(new User("John" + i, i)); + } + userList.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + } +} diff --git a/java-streams/src/main/java/com/baeldung/reduce/entities/User.java b/java-streams/src/main/java/com/baeldung/reduce/entities/User.java new file mode 100644 index 0000000000..a17c6a02b6 --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/reduce/entities/User.java @@ -0,0 +1,25 @@ +package com.baeldung.reduce.entities; + +public class User { + + private final String name; + private final int age; + + public User(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return "User{" + "name=" + name + ", age=" + age + '}'; + } +} diff --git a/java-streams/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java b/java-streams/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java new file mode 100644 index 0000000000..8b4af2cbe2 --- /dev/null +++ b/java-streams/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java @@ -0,0 +1,52 @@ +package com.baeldung.reduce.utilities; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.logging.Level; +import java.util.logging.Logger; + +public abstract class NumberUtils { + + private static final Logger LOGGER = Logger.getLogger(NumberUtils.class.getName()); + + public static int divideListElements(List values, Integer divider) { + return values.stream() + .reduce(0, (a, b) -> { + try { + return a / divider + b / divider; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return 0; + }); + } + + public static int divideListElementsWithExtractedTryCatchBlock(List values, int divider) { + return values.stream().reduce(0, (a, b) -> divide(a, divider) + divide(b, divider)); + } + + public static int divideListElementsWithApplyFunctionMethod(List values, int divider) { + BiFunction division = (a, b) -> a / b; + return values.stream().reduce(0, (a, b) -> applyFunction(division, a, divider) + applyFunction(division, b, divider)); + } + + private static int divide(int value, int factor) { + int result = 0; + try { + result = value / factor; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return result; + } + + private static int applyFunction(BiFunction function, int a, int b) { + try { + return function.apply(a, b); + } + catch(Exception e) { + LOGGER.log(Level.INFO, "Exception occurred!"); + } + return 0; + } +} diff --git a/java-streams/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java b/java-streams/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java new file mode 100644 index 0000000000..8e2ff7bf22 --- /dev/null +++ b/java-streams/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java @@ -0,0 +1,79 @@ +package com.baeldung.reduce.tests; + +import com.baeldung.reduce.entities.User; +import com.baeldung.reduce.utilities.NumberUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class StreamReduceUnitTest { + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorLambda_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result = numbers.stream().reduce(0, (a, b) -> a + b); + assertThat(result).isEqualTo(21); + } + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorMethodReference_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result = numbers.stream().reduce(0, Integer::sum); + assertThat(result).isEqualTo(21); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorLambda_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.stream().reduce("", (a, b) -> a + b); + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorMethodReference_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.stream().reduce("", String::concat); + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithUppercaseConcatenatorAccumulator_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.stream().reduce("", (a, b) -> a.toUpperCase() + b.toUpperCase()); + assertThat(result).isEqualTo("ABCDE"); + } + + @Test + public void givenUserList_whenReduceWithAgeAccumulatorAndSumCombiner_thenCorrect() { + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + int result = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + assertThat(result).isEqualTo(65); + } + + @Test + public void givenStringList_whenReduceWithParallelStream_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.parallelStream().reduce("", String::concat); + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElements_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + assertThat(NumberUtils.divideListElements(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlock_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenStream_whneCalleddivideListElementsWithApplyFunctionMethod_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + assertThat(NumberUtils.divideListElementsWithApplyFunctionMethod(numbers, 1)).isEqualTo(21); + } +} From c37d369f3a064cb92501978b9827d26af6ccfdc0 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 27 Feb 2019 20:37:12 +0530 Subject: [PATCH 126/496] BAEL-12770 Aligning module name, artifact id and folder name --- jhipster/jhipster-uaa/pom.xml | 3 +-- spring-soap/pom.xml | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/jhipster/jhipster-uaa/pom.xml b/jhipster/jhipster-uaa/pom.xml index 88df59b735..2c890c7b41 100644 --- a/jhipster/jhipster-uaa/pom.xml +++ b/jhipster/jhipster-uaa/pom.xml @@ -2,9 +2,8 @@ 4.0.0 - com.baeldung.jhipster jhipster-microservice-uaa - JHipster Microservice with UAA + jhipster-microservice-uaa pom diff --git a/spring-soap/pom.xml b/spring-soap/pom.xml index f5c3a1434d..ba05eddf5d 100644 --- a/spring-soap/pom.xml +++ b/spring-soap/pom.xml @@ -2,9 +2,8 @@ 4.0.0 - - com.baeldung spring-soap + spring-soap 1.0.0 From 9c12b713a3111195ad83b868c5592321db83634f Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 27 Feb 2019 20:54:15 +0530 Subject: [PATCH 127/496] BAEL-10995 Fix integration build of spring-data-elasticsearch module -Included project in the main pom.xml --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 820b43a141..0a401299ba 100644 --- a/pom.xml +++ b/pom.xml @@ -542,7 +542,7 @@ persistence-modules/spring-data-couchbase-2 persistence-modules/spring-data-dynamodb persistence-modules/spring-data-eclipselink - + persistence-modules/spring-data-elasticsearch persistence-modules/spring-data-gemfire persistence-modules/spring-data-jpa persistence-modules/spring-data-keyvalue @@ -1260,7 +1260,7 @@ persistence-modules/spring-data-couchbase-2 persistence-modules/spring-data-dynamodb persistence-modules/spring-data-eclipselink - + persistence-modules/spring-data-elasticsearch persistence-modules/spring-data-gemfire persistence-modules/spring-data-jpa persistence-modules/spring-data-keyvalue From 0daef8c86413b8c070159ada436e210a30750b5c Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 27 Feb 2019 21:54:08 +0530 Subject: [PATCH 128/496] BAEL-12771 Updated spring-cloud-dependencies to Greenwich.RELEASE which is available in maven central --- spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml | 2 +- spring-cloud-data-flow/etl/customer-transform/pom.xml | 2 +- spring-cloud/spring-cloud-vault/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml b/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml index 369247f370..456caf480c 100644 --- a/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml +++ b/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml @@ -64,7 +64,7 @@ UTF-8 UTF-8 1.8 - Greenwich.M3 + Greenwich.RELEASE diff --git a/spring-cloud-data-flow/etl/customer-transform/pom.xml b/spring-cloud-data-flow/etl/customer-transform/pom.xml index 2b650c80bb..b7376f7bd4 100644 --- a/spring-cloud-data-flow/etl/customer-transform/pom.xml +++ b/spring-cloud-data-flow/etl/customer-transform/pom.xml @@ -56,7 +56,7 @@ UTF-8 UTF-8 1.8 - Greenwich.M3 + Greenwich.RELEASE diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml index 766dfa10c7..3466f657be 100644 --- a/spring-cloud/spring-cloud-vault/pom.xml +++ b/spring-cloud/spring-cloud-vault/pom.xml @@ -69,7 +69,7 @@ UTF-8 UTF-8 1.8 - Greenwich.M3 + Greenwich.RELEASE From c575ba8d6fc32c6d523bd9d73170b90250756e22 Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 27 Feb 2019 20:54:22 +0300 Subject: [PATCH 129/496] Issue 6427 fix incompatible dependencies (#6428) * fix 6427 - update Spring Boot to 2.1.3, update Spring Cloud to Greenwich.RELEASE * cleanup: specify Thymeleaf namespace, `@ComponentScan` is redundant near `@SpringBootApplication` --- parent-boot-2/pom.xml | 4 +--- spring-boot-bootstrap/pom.xml | 6 +++--- .../src/main/java/com/baeldung/Application.java | 4 +--- .../src/main/resources/templates/error.html | 10 +++++----- .../src/main/resources/templates/home.html | 4 ++-- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml index 280d226e95..ef156e2e6a 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -78,8 +78,6 @@ 3.1.0 1.0.11.RELEASE - 2.1.1.RELEASE + 2.1.3.RELEASE - - diff --git a/spring-boot-bootstrap/pom.xml b/spring-boot-bootstrap/pom.xml index f13801f532..70ebb225c8 100644 --- a/spring-boot-bootstrap/pom.xml +++ b/spring-boot-bootstrap/pom.xml @@ -84,7 +84,7 @@ openshift 0.3.0.RELEASE - Finchley.SR2 + Greenwich.RELEASE 3.5.37 @@ -166,7 +166,7 @@ org.springframework.cloud spring-cloud-dependencies - Finchley.SR1 + Greenwich.RELEASE pom import @@ -214,7 +214,7 @@ org.springframework.cloud spring-cloud-dependencies - Finchley.SR1 + Greenwich.RELEASE pom import diff --git a/spring-boot-bootstrap/src/main/java/com/baeldung/Application.java b/spring-boot-bootstrap/src/main/java/com/baeldung/Application.java index 567e9b2678..d5a597e48b 100644 --- a/spring-boot-bootstrap/src/main/java/com/baeldung/Application.java +++ b/spring-boot-bootstrap/src/main/java/com/baeldung/Application.java @@ -4,12 +4,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.web.servlet.ServletComponentScan; -import org.springframework.context.annotation.ComponentScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @ServletComponentScan -@SpringBootApplication -@ComponentScan("com.baeldung") +@SpringBootApplication(scanBasePackages = "com.baeldung") @EnableJpaRepositories("com.baeldung.persistence.repo") @EntityScan("com.baeldung.persistence.model") public class Application { diff --git a/spring-boot-bootstrap/src/main/resources/templates/error.html b/spring-boot-bootstrap/src/main/resources/templates/error.html index f2b51a1938..ca3a740b71 100644 --- a/spring-boot-bootstrap/src/main/resources/templates/error.html +++ b/spring-boot-bootstrap/src/main/resources/templates/error.html @@ -1,19 +1,19 @@ - + Error Occurred
-

Error Occurred!

-
- \ No newline at end of file + diff --git a/spring-boot-bootstrap/src/main/resources/templates/home.html b/spring-boot-bootstrap/src/main/resources/templates/home.html index 5707cfb82a..0428ca1127 100644 --- a/spring-boot-bootstrap/src/main/resources/templates/home.html +++ b/spring-boot-bootstrap/src/main/resources/templates/home.html @@ -1,7 +1,7 @@ - + Home Page

Hello !

Welcome to Our App

- \ No newline at end of file + From d78a72cb4dd66c435c2b7f2d7b435ff288c0e56c Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 27 Feb 2019 23:53:48 +0530 Subject: [PATCH 130/496] BAEL-12771 Fixed pom for spring-zuul --- spring-zuul/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-zuul/pom.xml b/spring-zuul/pom.xml index c26c75cf07..fbbbdddbf7 100644 --- a/spring-zuul/pom.xml +++ b/spring-zuul/pom.xml @@ -38,7 +38,7 @@ - 2.1.0.RC3 + 2.1.0.RELEASE 3.5 From 8915610193c0711cdfd1b9040c14059e62c8c222 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 27 Feb 2019 20:37:12 +0530 Subject: [PATCH 131/496] BAEL-12770 Aligning module name, artifact id and folder name --- jhipster/jhipster-uaa/pom.xml | 3 +-- lombok-custom/pom.xml | 1 + maven/custom-rule/pom.xml | 1 + maven/maven-enforcer/pom.xml | 1 + osgi/osgi-intro-sample-activator/pom.xml | 1 + osgi/osgi-intro-sample-client/pom.xml | 1 + osgi/osgi-intro-sample-service/pom.xml | 1 + patterns/solid/pom.xml | 1 + restx/pom.xml | 2 +- rxjava-2/pom.xml | 1 + spring-boot-angular/pom.xml | 3 ++- spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml | 1 + .../spring-cloud-kubernetes/readiness-example/pom.xml | 1 + spring-cloud/spring-cloud-vault/pom.xml | 2 +- .../remoting-hessian-burlap-client/pom.xml | 4 ++-- spring-soap/pom.xml | 3 +-- spring-zuul/pom.xml | 2 +- 17 files changed, 19 insertions(+), 10 deletions(-) diff --git a/jhipster/jhipster-uaa/pom.xml b/jhipster/jhipster-uaa/pom.xml index 88df59b735..2c890c7b41 100644 --- a/jhipster/jhipster-uaa/pom.xml +++ b/jhipster/jhipster-uaa/pom.xml @@ -2,9 +2,8 @@ 4.0.0 - com.baeldung.jhipster jhipster-microservice-uaa - JHipster Microservice with UAA + jhipster-microservice-uaa pom diff --git a/lombok-custom/pom.xml b/lombok-custom/pom.xml index f016405fd6..cfbe629945 100644 --- a/lombok-custom/pom.xml +++ b/lombok-custom/pom.xml @@ -5,6 +5,7 @@ 4.0.0 lombok-custom + lombok-custom 0.1-SNAPSHOT diff --git a/maven/custom-rule/pom.xml b/maven/custom-rule/pom.xml index f76e0db11e..25a3489fb9 100644 --- a/maven/custom-rule/pom.xml +++ b/maven/custom-rule/pom.xml @@ -9,6 +9,7 @@ 4.0.0 custom-rule + custom-rule 3.0.0-M2 diff --git a/maven/maven-enforcer/pom.xml b/maven/maven-enforcer/pom.xml index d54471e66c..9826beb0d9 100644 --- a/maven/maven-enforcer/pom.xml +++ b/maven/maven-enforcer/pom.xml @@ -9,6 +9,7 @@ 4.0.0 maven-enforcer + maven-enforcer diff --git a/osgi/osgi-intro-sample-activator/pom.xml b/osgi/osgi-intro-sample-activator/pom.xml index 95ac1fc0fb..2bc1c20eed 100644 --- a/osgi/osgi-intro-sample-activator/pom.xml +++ b/osgi/osgi-intro-sample-activator/pom.xml @@ -3,6 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 osgi-intro-sample-activator + osgi-intro-sample-activator bundle diff --git a/osgi/osgi-intro-sample-client/pom.xml b/osgi/osgi-intro-sample-client/pom.xml index 7f5faedb30..a630625ed2 100644 --- a/osgi/osgi-intro-sample-client/pom.xml +++ b/osgi/osgi-intro-sample-client/pom.xml @@ -5,6 +5,7 @@ 4.0.0 osgi-intro-sample-client + osgi-intro-sample-client bundle diff --git a/osgi/osgi-intro-sample-service/pom.xml b/osgi/osgi-intro-sample-service/pom.xml index 8f81645ad4..4f0b108837 100644 --- a/osgi/osgi-intro-sample-service/pom.xml +++ b/osgi/osgi-intro-sample-service/pom.xml @@ -3,6 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 osgi-intro-sample-service + osgi-intro-sample-service bundle diff --git a/patterns/solid/pom.xml b/patterns/solid/pom.xml index 2837504197..146a9903cf 100644 --- a/patterns/solid/pom.xml +++ b/patterns/solid/pom.xml @@ -5,6 +5,7 @@ 4.0.0 com.baeldung solid + solid 1.0-SNAPSHOT diff --git a/restx/pom.xml b/restx/pom.xml index cc503f89b6..3a2e6af6f5 100644 --- a/restx/pom.xml +++ b/restx/pom.xml @@ -5,7 +5,7 @@ 4.0.0 restx 0.1-SNAPSHOT - restx-demo + restx war diff --git a/rxjava-2/pom.xml b/rxjava-2/pom.xml index 2519516f45..47d16ec8dd 100644 --- a/rxjava-2/pom.xml +++ b/rxjava-2/pom.xml @@ -4,6 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 rxjava-2 + rxjava-2 1.0-SNAPSHOT diff --git a/spring-boot-angular/pom.xml b/spring-boot-angular/pom.xml index f2ed6d7718..6ea98eb3d0 100644 --- a/spring-boot-angular/pom.xml +++ b/spring-boot-angular/pom.xml @@ -2,7 +2,8 @@ 4.0.0 com.baeldung.springbootangular - springbootangular + spring-boot-angular + spring-boot-angular 1.0 jar diff --git a/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml index b87f807391..012a81bd8d 100644 --- a/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/liveness-example/pom.xml @@ -4,6 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 liveness-example + liveness-example 1.0-SNAPSHOT diff --git a/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml b/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml index 42fa10934b..2b2e57a19c 100644 --- a/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/readiness-example/pom.xml @@ -4,6 +4,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 readiness-example + readiness-example 1.0-SNAPSHOT diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml index abfb0d06f3..fbcf8508c9 100644 --- a/spring-cloud/spring-cloud-vault/pom.xml +++ b/spring-cloud/spring-cloud-vault/pom.xml @@ -80,7 +80,7 @@ UTF-8 UTF-8 1.8 - Greenwich.M3 + Greenwich.RELEASE diff --git a/spring-remoting/remoting-hessian-burlap/remoting-hessian-burlap-client/pom.xml b/spring-remoting/remoting-hessian-burlap/remoting-hessian-burlap-client/pom.xml index 104712c3d7..ec237ca815 100644 --- a/spring-remoting/remoting-hessian-burlap/remoting-hessian-burlap-client/pom.xml +++ b/spring-remoting/remoting-hessian-burlap/remoting-hessian-burlap-client/pom.xml @@ -3,8 +3,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - spring-remoting-hessian-burlap-client - spring-remoting-hessian-burlap-client + remoting-hessian-burlap-client + remoting-hessian-burlap-client remoting-hessian-burlap diff --git a/spring-soap/pom.xml b/spring-soap/pom.xml index f5c3a1434d..ba05eddf5d 100644 --- a/spring-soap/pom.xml +++ b/spring-soap/pom.xml @@ -2,9 +2,8 @@ 4.0.0 - - com.baeldung spring-soap + spring-soap 1.0.0 diff --git a/spring-zuul/pom.xml b/spring-zuul/pom.xml index d00a932168..b33aef780b 100644 --- a/spring-zuul/pom.xml +++ b/spring-zuul/pom.xml @@ -38,7 +38,7 @@ - 2.1.0.RC3 + 2.1.0.RELEASE 3.5 From f88f01feb2a6f0ce8da840824df1345d9ca75849 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Thu, 28 Feb 2019 00:18:47 +0530 Subject: [PATCH 132/496] BAEL-12770 Reverted dependency version changes --- spring-cloud/spring-cloud-vault/pom.xml | 2 +- spring-zuul/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-cloud/spring-cloud-vault/pom.xml b/spring-cloud/spring-cloud-vault/pom.xml index fbcf8508c9..abfb0d06f3 100644 --- a/spring-cloud/spring-cloud-vault/pom.xml +++ b/spring-cloud/spring-cloud-vault/pom.xml @@ -80,7 +80,7 @@ UTF-8 UTF-8 1.8 - Greenwich.RELEASE + Greenwich.M3 diff --git a/spring-zuul/pom.xml b/spring-zuul/pom.xml index b33aef780b..d00a932168 100644 --- a/spring-zuul/pom.xml +++ b/spring-zuul/pom.xml @@ -38,7 +38,7 @@ - 2.1.0.RELEASE + 2.1.0.RC3 3.5 From 8f0735c54956be44758ed853135036194a735a05 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Wed, 27 Feb 2019 22:12:11 +0200 Subject: [PATCH 133/496] Update README.md --- core-java/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java/README.md b/core-java/README.md index d2fd903c10..1143604eac 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -19,7 +19,6 @@ - [Introduction to Java Serialization](http://www.baeldung.com/java-serialization) - [Guide to UUID in Java](http://www.baeldung.com/java-uuid) - [Guide to Escaping Characters in Java RegExps](http://www.baeldung.com/java-regexp-escape-char) -- [Difference between URL and URI](http://www.baeldung.com/java-url-vs-uri) - [Creating a Java Compiler Plugin](http://www.baeldung.com/java-build-compiler-plugin) - [Quick Guide to Java Stack](http://www.baeldung.com/java-stack) - [Compiling Java *.class Files with javac](http://www.baeldung.com/javac) From b170f8f5b09bbfa12f65247731b3209b47f55a22 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Wed, 27 Feb 2019 22:12:38 +0200 Subject: [PATCH 134/496] Update README.md --- core-java-networking/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-java-networking/README.md b/core-java-networking/README.md index b2367782b6..40be47fbcc 100644 --- a/core-java-networking/README.md +++ b/core-java-networking/README.md @@ -13,4 +13,5 @@ - [Working with Network Interfaces in Java](http://www.baeldung.com/java-network-interfaces) - [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets) - [URL Encoding and Decoding in Java](http://www.baeldung.com/java-url-encoding-decoding) -- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request) \ No newline at end of file +- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request) +- [Difference between URL and URI](http://www.baeldung.com/java-url-vs-uri) From 072e2232b08aaf27c194be5e86f527decd386b1e Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 17:00:45 +0800 Subject: [PATCH 135/496] Update README.MD --- persistence-modules/spring-boot-persistence/README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/spring-boot-persistence/README.MD b/persistence-modules/spring-boot-persistence/README.MD index 6fe5e6f05f..f62ca57a19 100644 --- a/persistence-modules/spring-boot-persistence/README.MD +++ b/persistence-modules/spring-boot-persistence/README.MD @@ -2,7 +2,7 @@ - [Spring Boot with Multiple SQL Import Files](http://www.baeldung.com/spring-boot-sql-import-files) - [Configuring Separate Spring DataSource for Tests](http://www.baeldung.com/spring-testing-separate-data-source) -- [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql) +- [Quick Guide on Loading Initial Data with Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql) - [Configuring a Tomcat Connection Pool in Spring Boot](https://www.baeldung.com/spring-boot-tomcat-connection-pool) - [Hibernate Field Naming with Spring Boot](https://www.baeldung.com/hibernate-field-naming-spring-boot) - [Integrating Spring Boot with HSQLDB](https://www.baeldung.com/spring-boot-hsqldb) From 397ca5b59f946312255e7c0f289554c2614a2cce Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 17:18:43 +0800 Subject: [PATCH 136/496] Update README.MD --- spring-cloud/spring-cloud-gateway/README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud/spring-cloud-gateway/README.MD b/spring-cloud/spring-cloud-gateway/README.MD index 48fbf41b8e..d945ae949c 100644 --- a/spring-cloud/spring-cloud-gateway/README.MD +++ b/spring-cloud/spring-cloud-gateway/README.MD @@ -1,2 +1,2 @@ ### Relevant Articles: -- [Explore the new Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway) +- [Exploring the new Spring Cloud Gateway](http://www.baeldung.com/spring-cloud-gateway) From 0661a109c7226a97b052599ae74ced53eb8b58a1 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 17:23:21 +0800 Subject: [PATCH 137/496] Update README.md --- jooby/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jooby/README.md b/jooby/README.md index 032e595354..aa867b2c56 100644 --- a/jooby/README.md +++ b/jooby/README.md @@ -1,3 +1,3 @@ ## Relevant articles: -- [Introduction to Jooby Project](http://www.baeldung.com/jooby) +- [Introduction to Jooby](http://www.baeldung.com/jooby) From b41efaaf6b851d7147185616f17a3548f3bb203e Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 17:30:09 +0800 Subject: [PATCH 138/496] Update README.md --- vavr/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vavr/README.md b/vavr/README.md index 0857765ec6..266cae91bb 100644 --- a/vavr/README.md +++ b/vavr/README.md @@ -4,7 +4,7 @@ - [Guide to Pattern Matching in Vavr](http://www.baeldung.com/vavr-pattern-matching) - [Property Testing Example With Vavr](http://www.baeldung.com/vavr-property-testing) - [Exceptions in Lambda Expression Using Vavr](http://www.baeldung.com/exceptions-using-vavr) -- [Vavr (ex-Javaslang) Support in Spring Data](http://www.baeldung.com/spring-vavr) +- [Vavr Support in Spring Data](http://www.baeldung.com/spring-vavr) - [Introduction to Vavr’s Validation API](http://www.baeldung.com/vavr-validation-api) - [Guide to Collections API in Vavr](http://www.baeldung.com/vavr-collections) - [Collection Factory Methods for Vavr](http://www.baeldung.com/vavr-collection-factory-methods) From dad532bb537432a225f39b9814f326eefeafc324 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 17:32:45 +0800 Subject: [PATCH 139/496] Update README.md --- testing-modules/junit-5/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md index 4ed01e7fa9..e68d72efe3 100644 --- a/testing-modules/junit-5/README.md +++ b/testing-modules/junit-5/README.md @@ -3,7 +3,7 @@ - [A Guide to JUnit 5](http://www.baeldung.com/junit-5) - [A Guide to @RepeatedTest in Junit 5](http://www.baeldung.com/junit-5-repeated-test) - [Guide to Dynamic Tests in Junit 5](http://www.baeldung.com/junit5-dynamic-tests) -- [A Guied to JUnit 5 Extensions](http://www.baeldung.com/junit-5-extensions) +- [A Guide to JUnit 5 Extensions](http://www.baeldung.com/junit-5-extensions) - [Inject Parameters into JUnit Jupiter Unit Tests](http://www.baeldung.com/junit-5-parameters) - [Mockito and JUnit 5 – Using ExtendWith](http://www.baeldung.com/mockito-junit-5-extension) - [JUnit 5 – @RunWith](http://www.baeldung.com/junit-5-runwith) From f7e2c8062304e551e9fa0bb62fd92a90ead9b17b Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 17:35:28 +0800 Subject: [PATCH 140/496] Update README.md --- spring-5-reactive/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md index c39bb616f8..119e57f256 100644 --- a/spring-5-reactive/README.md +++ b/spring-5-reactive/README.md @@ -7,7 +7,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web) - [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient) -- [Exploring the Spring 5 MVC URL Matching Improvements](http://www.baeldung.com/spring-5-mvc-url-matching) +- [Exploring the Spring 5 MVC URL Matching](http://www.baeldung.com/spring-5-mvc-url-matching) - [Reactive WebSockets with Spring 5](http://www.baeldung.com/spring-5-reactive-websockets) - [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters) - [How to Set a Header on a Response with Spring 5](http://www.baeldung.com/spring-response-header) From af1f80f1469730055ea81a94652cd564f0d94084 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 17:46:06 +0800 Subject: [PATCH 141/496] Update README.md --- core-kotlin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 6ee79b2a2e..45163b3f99 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -4,7 +4,7 @@ - [A guide to the “when{}” block in Kotlin](http://www.baeldung.com/kotlin-when) - [Comprehensive Guide to Null Safety in Kotlin](http://www.baeldung.com/kotlin-null-safety) - [Kotlin Java Interoperability](http://www.baeldung.com/kotlin-java-interoperability) -- [Difference Between “==” and “===” in Kotlin](http://www.baeldung.com/kotlin-equality-operators) +- [Difference Between “==” and “===” operators in Kotlin](http://www.baeldung.com/kotlin-equality-operators) - [Generics in Kotlin](http://www.baeldung.com/kotlin-generics) - [Introduction to Kotlin Coroutines](http://www.baeldung.com/kotlin-coroutines) - [Destructuring Declarations in Kotlin](http://www.baeldung.com/kotlin-destructuring-declarations) From df5e2493c1c05f1016283fd36058d02791734973 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 17:53:09 +0800 Subject: [PATCH 142/496] Update README.md --- core-java-networking/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-networking/README.md b/core-java-networking/README.md index b2367782b6..dd4ee1e151 100644 --- a/core-java-networking/README.md +++ b/core-java-networking/README.md @@ -13,4 +13,4 @@ - [Working with Network Interfaces in Java](http://www.baeldung.com/java-network-interfaces) - [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets) - [URL Encoding and Decoding in Java](http://www.baeldung.com/java-url-encoding-decoding) -- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request) \ No newline at end of file +- [Do a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request) From 9ac6c2c8de8bf5fd27da13e9d8ba0bbe187e4791 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 19:23:55 +0800 Subject: [PATCH 143/496] Update README.md --- spring-rest/src/main/java/com/baeldung/produceimage/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-rest/src/main/java/com/baeldung/produceimage/README.md b/spring-rest/src/main/java/com/baeldung/produceimage/README.md index acd546598d..4aeadea546 100644 --- a/spring-rest/src/main/java/com/baeldung/produceimage/README.md +++ b/spring-rest/src/main/java/com/baeldung/produceimage/README.md @@ -1,3 +1,3 @@ ### Relevant articles -- [Returning an Image or a File with Spring](http://www.baeldung.com/spring-controller-return-image-file) +- [Download an Image or a File with Spring MVC](http://www.baeldung.com/spring-controller-return-image-file) From c9c6f879d08a72e0ce89d9e03ef98acdf9cd4048 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 19:45:23 +0800 Subject: [PATCH 144/496] Update README.md --- spark-java/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spark-java/README.md b/spark-java/README.md index 711607bd4e..5abe78263c 100644 --- a/spark-java/README.md +++ b/spark-java/README.md @@ -3,4 +3,4 @@ ## Spark Java Framework Tutorial Sample Project ### Relevant Articles -- [Intro to Spark Java Framework](http://www.baeldung.com/spark-framework-rest-api) +- [Building an API With the Spark Java Framework](http://www.baeldung.com/spark-framework-rest-api) From ffe5768eef005a83b8429620e78f961042c999e2 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 19:50:20 +0800 Subject: [PATCH 145/496] Update README.md --- spring-security-core/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-core/README.md b/spring-security-core/README.md index f7b3f6dffe..b38dc061b4 100644 --- a/spring-security-core/README.md +++ b/spring-security-core/README.md @@ -7,6 +7,6 @@ mvn clean install ``` ### Relevant Articles: -- [Intro to @PreFilter and @PostFilter in Spring Security](http://www.baeldung.com/spring-security-prefilter-postfilter) +- [Spring Security – @PreFilter and @PostFilter](http://www.baeldung.com/spring-security-prefilter-postfilter) - [Spring Boot Authentication Auditing Support](http://www.baeldung.com/spring-boot-authentication-audit) - [Introduction to Spring Method Security](http://www.baeldung.com/spring-security-method-security) From 0f5d447fac99e8506461ff11b6332a9e688cfd3e Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 19:53:36 +0800 Subject: [PATCH 146/496] Update README.md --- core-java-networking/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-networking/README.md b/core-java-networking/README.md index dd4ee1e151..f6ce44d72f 100644 --- a/core-java-networking/README.md +++ b/core-java-networking/README.md @@ -12,5 +12,5 @@ - [A Guide to the Java URL](http://www.baeldung.com/java-url) - [Working with Network Interfaces in Java](http://www.baeldung.com/java-network-interfaces) - [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets) -- [URL Encoding and Decoding in Java](http://www.baeldung.com/java-url-encoding-decoding) +- [Guide to Java URL Encoding/Decoding](http://www.baeldung.com/java-url-encoding-decoding) - [Do a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request) From 433af3993b093cd9a1bab12fc7fd629bcb118016 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 19:55:45 +0800 Subject: [PATCH 147/496] Update README.md --- core-java-io/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-io/README.md b/core-java-io/README.md index 9a25009849..ac6d5c4eee 100644 --- a/core-java-io/README.md +++ b/core-java-io/README.md @@ -11,7 +11,7 @@ - [Java – Byte Array to Writer](http://www.baeldung.com/java-convert-byte-array-to-writer) - [Java – Directory Size](http://www.baeldung.com/java-folder-size) - [Differences Between the Java WatchService API and the Apache Commons IO Monitor Library](http://www.baeldung.com/java-watchservice-vs-apache-commons-io-monitor-library) -- [Calculate the Size of a File in Java](http://www.baeldung.com/java-file-size) +- [File Size in Java](http://www.baeldung.com/java-file-size) - [Comparing getPath(), getAbsolutePath(), and getCanonicalPath() in Java](http://www.baeldung.com/java-path) - [Using Java MappedByteBuffer](http://www.baeldung.com/java-mapped-byte-buffer) - [Copy a File with Java](http://www.baeldung.com/java-copy-file) From dea68e021be5601723e094967ed76429083b9afa Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 19:57:32 +0800 Subject: [PATCH 148/496] Update README.md --- core-java-lang-syntax/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-lang-syntax/README.md b/core-java-lang-syntax/README.md index 99c8613929..e77a8a58cb 100644 --- a/core-java-lang-syntax/README.md +++ b/core-java-lang-syntax/README.md @@ -3,7 +3,7 @@ ## Core Java Lang Syntax Cookbooks and Examples ### Relevant Articles: -- [Introduction to Java Generics](http://www.baeldung.com/java-generics) +- [The Basics of Java Generics](http://www.baeldung.com/java-generics) - [Java Primitive Conversions](http://www.baeldung.com/java-primitive-conversions) - [Java Double Brace Initialization](http://www.baeldung.com/java-double-brace-initialization) - [Guide to the Diamond Operator in Java](http://www.baeldung.com/java-diamond-operator) From 296f70dde9c1f9632a0c9b625d2ffc973358119d Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 19:58:41 +0800 Subject: [PATCH 149/496] Update README.md --- core-java-security/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-security/README.md b/core-java-security/README.md index d3343f79ca..9526b15be5 100644 --- a/core-java-security/README.md +++ b/core-java-security/README.md @@ -8,5 +8,5 @@ - [Encrypting and Decrypting Files in Java](http://www.baeldung.com/java-cipher-input-output-stream) - [Hashing a Password in Java](https://www.baeldung.com/java-password-hashing) - [SSL Handshake Failures](https://www.baeldung.com/java-ssl-handshake-failures) -- [SHA-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java) +- [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java) - [Enabling TLS v1.2 in Java 7](https://www.baeldung.com/java-7-tls-v12) From 76ecabe9614050691e4bbda9e83d5f7eb901ab34 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:04:22 +0800 Subject: [PATCH 150/496] Update README.md --- spring-security-rest-basic-auth/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-rest-basic-auth/README.md b/spring-security-rest-basic-auth/README.md index f92fcfe36b..0c97b9b592 100644 --- a/spring-security-rest-basic-auth/README.md +++ b/spring-security-rest-basic-auth/README.md @@ -9,5 +9,5 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [RestTemplate with Basic Authentication in Spring](http://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring) - [HttpClient Timeout](http://www.baeldung.com/httpclient-timeout) - [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl) -- [Writing a Custom Filter in Spring Security](http://www.baeldung.com/spring-security-custom-filter) +- [A Custom Filter in the Spring Security Filter Chain](http://www.baeldung.com/spring-security-custom-filter) - [Spring Security Basic Authentication](http://www.baeldung.com/spring-security-basic-authentication) From 44c22f4fe77e283edad111dab826616d6712d9df Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:05:37 +0800 Subject: [PATCH 151/496] Update README.md --- spring-jms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-jms/README.md b/spring-jms/README.md index b942cc72a0..55e74f18ff 100644 --- a/spring-jms/README.md +++ b/spring-jms/README.md @@ -1,2 +1,2 @@ ### Relevant Articles: -- [An Introduction To Spring JMS](http://www.baeldung.com/spring-jms) +- [Getting Started with Spring JMS](http://www.baeldung.com/spring-jms) From 2480c458b9d05e6bc9218b2419ce583941b4f5f1 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:09:34 +0800 Subject: [PATCH 152/496] Update README.md --- core-java-collections-list/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md index 3a4a7c69e8..5fe84480db 100644 --- a/core-java-collections-list/README.md +++ b/core-java-collections-list/README.md @@ -5,7 +5,7 @@ ### Relevant Articles: - [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list) - [Guide to the Java ArrayList](http://www.baeldung.com/java-arraylist) -- [Random List Element](http://www.baeldung.com/java-random-list-element) +- [Java – Get Random Item/Element From a List](http://www.baeldung.com/java-random-list-element) - [Removing all nulls from a List in Java](http://www.baeldung.com/java-remove-nulls-from-list) - [Removing all duplicates from a List in Java](http://www.baeldung.com/java-remove-duplicates-from-list) - [How to TDD a List Implementation in Java](http://www.baeldung.com/java-test-driven-list) From 98325175c57c78cbd246c7d3978d2e463ead77ec Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:16:14 +0800 Subject: [PATCH 153/496] Update README.md --- core-java-8/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-8/README.md b/core-java-8/README.md index 892dc71f76..fb4f54222d 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -4,7 +4,7 @@ ### Relevant Articles: - [Java 8 Collectors](http://www.baeldung.com/java-8-collectors) -- [Guide to Java 8’s Functional Interfaces](http://www.baeldung.com/java-8-functional-interfaces) +- [Functional Interfaces in Java 8](http://www.baeldung.com/java-8-functional-interfaces) - [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda) - [Java 8 New Features](http://www.baeldung.com/java-8-new-features) - [Lambda Expressions and Functional Interfaces: Tips and Best Practices](http://www.baeldung.com/java-8-lambda-expressions-tips) From 1a020467280fd9d3f465b84fcf4c9cd98e83a21d Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:18:10 +0800 Subject: [PATCH 154/496] Update README.md --- spring-all/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-all/README.md b/spring-all/README.md index 0d78efdcf2..791af2cb58 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -15,7 +15,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Profiles](http://www.baeldung.com/spring-profiles) - [A Spring Custom Annotation for a Better DAO](http://www.baeldung.com/spring-annotation-bean-pre-processor) - [What's New in Spring 4.3?](http://www.baeldung.com/whats-new-in-spring-4-3) -- [Guide To Running Logic on Startup in Spring](http://www.baeldung.com/running-setup-logic-on-startup-in-spring) +- [Running Setup Data on Startup in Spring](http://www.baeldung.com/running-setup-logic-on-startup-in-spring) - [Quick Guide to Spring Controllers](http://www.baeldung.com/spring-controllers) - [Quick Guide to Spring Bean Scopes](http://www.baeldung.com/spring-bean-scopes) - [Introduction To Ehcache](http://www.baeldung.com/ehcache) From 295bc9d070a1f9a9a8ec674acd89cb975543fbf3 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:19:16 +0800 Subject: [PATCH 155/496] Update README.md --- jsf/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsf/README.md b/jsf/README.md index 6e0891182d..d96c1eb8e3 100644 --- a/jsf/README.md +++ b/jsf/README.md @@ -1,5 +1,5 @@ ### Relevant Articles: -- [Introduction to JSF Expression Language 3.0](http://www.baeldung.com/jsf-expression-language-el-3) +- [Guide to JSF Expression Language 3.0](http://www.baeldung.com/jsf-expression-language-el-3) - [Introduction to JSF EL 2](http://www.baeldung.com/intro-to-jsf-expression-language) - [JavaServer Faces (JSF) with Spring](http://www.baeldung.com/spring-jsf) - [Introduction to Primefaces](http://www.baeldung.com/jsf-primefaces) From 53d1331ea8eafd8f3ee4bfb7ea834c43b7f547d1 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:20:47 +0800 Subject: [PATCH 156/496] Update README.md --- persistence-modules/spring-hibernate-5/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/spring-hibernate-5/README.md b/persistence-modules/spring-hibernate-5/README.md index 5e287919f1..c48e58fcca 100644 --- a/persistence-modules/spring-hibernate-5/README.md +++ b/persistence-modules/spring-hibernate-5/README.md @@ -2,4 +2,4 @@ - [Hibernate Many to Many Annotation Tutorial](http://www.baeldung.com/hibernate-many-to-many) - [Programmatic Transactions in the Spring TestContext Framework](http://www.baeldung.com/spring-test-programmatic-transactions) -- [Hibernate Criteria Queries](http://www.baeldung.com/hibernate-criteria-queries) +- [JPA Criteria Queries](http://www.baeldung.com/hibernate-criteria-queries) From 44f84c548510f93ba7b5705ebea78d0d3d7763e8 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:23:44 +0800 Subject: [PATCH 157/496] Update README.md --- testing-modules/testing/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing-modules/testing/README.md b/testing-modules/testing/README.md index 849b578a55..e96b26ab41 100644 --- a/testing-modules/testing/README.md +++ b/testing-modules/testing/README.md @@ -3,7 +3,7 @@ ## Mutation Testing ### Relevant Articles: -- [Introduction to Mutation Testing Using the PITest Library](http://www.baeldung.com/java-mutation-testing-with-pitest) +- [Mutation Testing with PITest](http://www.baeldung.com/java-mutation-testing-with-pitest) - [Intro to JaCoCo](http://www.baeldung.com/jacoco) - [AssertJ’s Java 8 Features](http://www.baeldung.com/assertJ-java-8-features) - [AssertJ for Guava](http://www.baeldung.com/assertJ-for-guava) From cc5a956133d0b7b6bb426a15c2fce43d52a43ea7 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:25:32 +0800 Subject: [PATCH 158/496] Update README.md --- java-streams/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-streams/README.md b/java-streams/README.md index 15ea1c742a..b931c0d7d9 100644 --- a/java-streams/README.md +++ b/java-streams/README.md @@ -3,7 +3,7 @@ ## Java Streams Cookbooks and Examples ### Relevant Articles: -- [Java 8 Streams Advanced](http://www.baeldung.com/java-8-streams) +- [The Java 8 Stream API Tutorial](http://www.baeldung.com/java-8-streams) - [Introduction to Java 8 Streams](http://www.baeldung.com/java-8-streams-introduction) - [Java 8 and Infinite Streams](http://www.baeldung.com/java-inifinite-streams) - [Java 8 Stream findFirst() vs. findAny()](http://www.baeldung.com/java-stream-findfirst-vs-findany) From 850c0096662ae04b6db9a02026db9b5c6a909825 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:29:55 +0800 Subject: [PATCH 159/496] Update README.md --- core-java-8/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-8/README.md b/core-java-8/README.md index fb4f54222d..f601ea9d37 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -6,7 +6,7 @@ - [Java 8 Collectors](http://www.baeldung.com/java-8-collectors) - [Functional Interfaces in Java 8](http://www.baeldung.com/java-8-functional-interfaces) - [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda) -- [Java 8 New Features](http://www.baeldung.com/java-8-new-features) +- [New Features in Java 8](http://www.baeldung.com/java-8-new-features) - [Lambda Expressions and Functional Interfaces: Tips and Best Practices](http://www.baeldung.com/java-8-lambda-expressions-tips) - [The Double Colon Operator in Java 8](http://www.baeldung.com/java-8-double-colon-operator) - [Guide to Java 8 groupingBy Collector](http://www.baeldung.com/java-groupingby-collector) From b0eac9be89ede158fc9b139797ef2d1545641781 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:33:41 +0800 Subject: [PATCH 160/496] Update README.md --- persistence-modules/spring-data-couchbase-2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/spring-data-couchbase-2/README.md b/persistence-modules/spring-data-couchbase-2/README.md index 2e56b25fef..2b6a1faddf 100644 --- a/persistence-modules/spring-data-couchbase-2/README.md +++ b/persistence-modules/spring-data-couchbase-2/README.md @@ -1,7 +1,7 @@ ## Spring Data Couchbase Tutorial Project ### Relevant Articles: -- [Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase) +- [Intro to Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase) - [Entity Validation, Query Consistency, and Optimistic Locking in Spring Data Couchbase](http://www.baeldung.com/entity-validation-locking-and-query-consistency-in-spring-data-couchbase) - [Multiple Buckets and Spatial View Queries in Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase-buckets-and-spatial-view-queries) From 5ebfdee1501256f1c403ecfcb3132cf8bc0cb97f Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:35:00 +0800 Subject: [PATCH 161/496] Update README.md --- spring-katharsis/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-katharsis/README.md b/spring-katharsis/README.md index cf2a001760..2082de2dda 100644 --- a/spring-katharsis/README.md +++ b/spring-katharsis/README.md @@ -6,4 +6,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [JSON API in a Java Web Application](http://www.baeldung.com/json-api-java-spring-web-app) +- [JSON API in a Spring Application](http://www.baeldung.com/json-api-java-spring-web-app) From 847d694adfef47554d37f3cc8c4474b3e272d6a0 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:36:16 +0800 Subject: [PATCH 162/496] Update README.md --- spring-resttemplate/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-resttemplate/README.md b/spring-resttemplate/README.md index 1c8ddf73f9..353e9f955e 100644 --- a/spring-resttemplate/README.md +++ b/spring-resttemplate/README.md @@ -4,7 +4,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [Spring RestTemplate Tutorial](http://www.baeldung.com/rest-template) +- [The Guide to RestTemplate](http://www.baeldung.com/rest-template) - [Exploring the Spring Boot TestRestTemplate](http://www.baeldung.com/spring-boot-testresttemplate) - [Spring RestTemplate Error Handling](http://www.baeldung.com/spring-rest-template-error-handling) - [Configure a RestTemplate with RestTemplateBuilder](http://www.baeldung.com/spring-rest-template-builder) From fd4104c8fd668f3c89b9eb2bb8458f867ab397b7 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:39:35 +0800 Subject: [PATCH 163/496] Update README.md --- jackson/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jackson/README.md b/jackson/README.md index e201a06727..0806575367 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -17,7 +17,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Jackson JSON Tutorial](http://www.baeldung.com/jackson) - [Jackson – Working with Maps and nulls](http://www.baeldung.com/jackson-map-null-values-or-null-key) - [Jackson – Decide What Fields Get Serialized/Deserializaed](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not) -- [A Guide to Jackson Annotations](http://www.baeldung.com/jackson-annotations) +- [Jackson Annotation Examples](http://www.baeldung.com/jackson-annotations) - [Working with Tree Model Nodes in Jackson](http://www.baeldung.com/jackson-json-node-tree-model) - [Jackson vs Gson](http://www.baeldung.com/jackson-vs-gson) - [Intro to the Jackson ObjectMapper](http://www.baeldung.com/jackson-object-mapper-tutorial) From d9debd5daf484dc9e15a78da3401952f1888e88e Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:42:40 +0800 Subject: [PATCH 164/496] Update README.md --- testing-modules/mockito/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing-modules/mockito/README.md b/testing-modules/mockito/README.md index 158a1918e7..59954784f9 100644 --- a/testing-modules/mockito/README.md +++ b/testing-modules/mockito/README.md @@ -7,7 +7,7 @@ - [Mockito Verify Cookbook](http://www.baeldung.com/mockito-verify) - [Mockito When/Then Cookbook](http://www.baeldung.com/mockito-behavior) - [Mockito – Using Spies](http://www.baeldung.com/mockito-spy) -- [Mockito – @Mock, @Spy, @Captor and @InjectMocks](http://www.baeldung.com/mockito-annotations) +- [Getting Started with Mockito @Mock, @Spy, @Captor and @InjectMocks](http://www.baeldung.com/mockito-annotations) - [Mockito’s Mock Methods](http://www.baeldung.com/mockito-mock-methods) - [Introduction to PowerMock](http://www.baeldung.com/intro-to-powermock) - [Mocking Exception Throwing using Mockito](http://www.baeldung.com/mockito-exceptions) From 3728f2e2618000ba40a6186aba3ef78655aee0e1 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:47:08 +0800 Subject: [PATCH 165/496] Update README.md --- spring-security-rest-basic-auth/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-rest-basic-auth/README.md b/spring-security-rest-basic-auth/README.md index 0c97b9b592..30da3afbcf 100644 --- a/spring-security-rest-basic-auth/README.md +++ b/spring-security-rest-basic-auth/README.md @@ -6,7 +6,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: -- [RestTemplate with Basic Authentication in Spring](http://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring) +- [Basic Authentication with the RestTemplate](http://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring) - [HttpClient Timeout](http://www.baeldung.com/httpclient-timeout) - [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl) - [A Custom Filter in the Spring Security Filter Chain](http://www.baeldung.com/spring-security-custom-filter) From f463cc341e48444cd0ae32ce1cde7fb2c8c6abfa Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:48:31 +0800 Subject: [PATCH 166/496] Update README.md --- httpclient/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/README.md b/httpclient/README.md index 93e0f3c9e1..19886be750 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -14,7 +14,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Unshorten URLs with HttpClient](http://www.baeldung.com/unshorten-url-httpclient) - [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl) - [HttpClient 4 – Follow Redirects for POST](http://www.baeldung.com/httpclient-redirect-on-http-post) -- [HttpClient – Set Custom Header](http://www.baeldung.com/httpclient-custom-http-header) +- [Custom HTTP Header with the HttpClient](http://www.baeldung.com/httpclient-custom-http-header) - [HttpClient Basic Authentication](http://www.baeldung.com/httpclient-4-basic-authentication) - [Multipart Upload with HttpClient 4](http://www.baeldung.com/httpclient-multipart-upload) - [HttpAsyncClient Tutorial](http://www.baeldung.com/httpasyncclient-tutorial) From ffc4ab61b4421e4c4f72bcf5f5a5e47e8ea3d81c Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:49:57 +0800 Subject: [PATCH 167/496] Update README.md --- jackson/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jackson/README.md b/jackson/README.md index 0806575367..519673738f 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -10,7 +10,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array) - [Jackson Unmarshalling json with Unknown Properties](http://www.baeldung.com/jackson-deserialize-json-unknown-properties) - [Jackson – Custom Serializer](http://www.baeldung.com/jackson-custom-serialization) -- [Jackson – Custom Deserializer](http://www.baeldung.com/jackson-deserialization) +- [Getting Started with Custom Deserialization in Jackson](http://www.baeldung.com/jackson-deserialization) - [Jackson Exceptions – Problems and Solutions](http://www.baeldung.com/jackson-exception) - [Jackson Date](http://www.baeldung.com/jackson-serialize-dates) - [Jackson – Bidirectional Relationships](http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion) From 5b65fc65dc0a37465c414b7840fd5907dccb747a Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:51:04 +0800 Subject: [PATCH 168/496] Update README.md --- core-java-io/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-io/README.md b/core-java-io/README.md index ac6d5c4eee..5e0f7bfbd1 100644 --- a/core-java-io/README.md +++ b/core-java-io/README.md @@ -3,7 +3,7 @@ ## Core Java IO Cookbooks and Examples ### Relevant Articles: -- [Java - Reading a Large File Efficiently](http://www.baeldung.com/java-read-lines-large-file) +- [How to Read a Large File Efficiently with Java](http://www.baeldung.com/java-read-lines-large-file) - [Java InputStream to String](http://www.baeldung.com/convert-input-stream-to-string) - [Java – Write to File](http://www.baeldung.com/java-write-to-file) - [Java - Convert File to InputStream](http://www.baeldung.com/convert-file-to-input-stream) From 1b8f5e1837834c1506ebe269b8993150eed29336 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:54:45 +0800 Subject: [PATCH 169/496] Update README.md --- httpclient/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpclient/README.md b/httpclient/README.md index 19886be750..7c5122c5b8 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -21,4 +21,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [HttpClient 4 Tutorial](http://www.baeldung.com/httpclient-guide) - [Advanced HttpClient Configuration](http://www.baeldung.com/httpclient-advanced-config) - [HttpClient 4 – Do Not Follow Redirects](http://www.baeldung.com/httpclient-stop-follow-redirect) -- [HttpClient 4 – Setting a Custom User-Agent](http://www.baeldung.com/httpclient-user-agent-header) +- [Custom User-Agent in HttpClient 4](http://www.baeldung.com/httpclient-user-agent-header) From 4ddb3c8c6f936fcea37541d1d1287c79f84cbd69 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:56:39 +0800 Subject: [PATCH 170/496] Update README.md --- spring-all/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-all/README.md b/spring-all/README.md index 791af2cb58..6e392088d9 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -11,7 +11,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant articles: - [Guide to Spring @Autowired](http://www.baeldung.com/spring-autowire) -- [Properties with Spring](http://www.baeldung.com/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage +- [Properties with Spring and Spring Boot](http://www.baeldung.com/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage - [Spring Profiles](http://www.baeldung.com/spring-profiles) - [A Spring Custom Annotation for a Better DAO](http://www.baeldung.com/spring-annotation-bean-pre-processor) - [What's New in Spring 4.3?](http://www.baeldung.com/whats-new-in-spring-4-3) From db2454c10f6ebbca45a678e54b8a677174bb8157 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:57:35 +0800 Subject: [PATCH 171/496] Update README.md --- spring-mvc-xml/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-mvc-xml/README.md b/spring-mvc-xml/README.md index 3199118281..dbc6125424 100644 --- a/spring-mvc-xml/README.md +++ b/spring-mvc-xml/README.md @@ -8,7 +8,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [Servlet Session Timeout](http://www.baeldung.com/servlet-session-timeout) +- [Java Session Timeout](http://www.baeldung.com/servlet-session-timeout) - [Returning Image/Media Data with Spring MVC](http://www.baeldung.com/spring-mvc-image-media-data) - [Geolocation by IP in Java](http://www.baeldung.com/geolocation-by-ip-with-maxmind) - [Guide to JavaServer Pages (JSP)](http://www.baeldung.com/jsp) From 10fe310a930aae4bef7bf7954cd10e3017006931 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 20:59:23 +0800 Subject: [PATCH 172/496] Update README.md --- spring-security-mvc-session/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-mvc-session/README.md b/spring-security-mvc-session/README.md index fc44209640..ce40ed5f5f 100644 --- a/spring-security-mvc-session/README.md +++ b/spring-security-mvc-session/README.md @@ -7,7 +7,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [HttpSessionListener Example – Monitoring](http://www.baeldung.com/httpsessionlistener_with_metrics) -- [Spring Security Session Management](http://www.baeldung.com/spring-security-session) +- [Control the Session with Spring Security](http://www.baeldung.com/spring-security-session) ### Build the Project From 4df758c4e217ad57842ce0a61fbeb28b1b233510 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 21:00:50 +0800 Subject: [PATCH 173/496] Update README.md --- persistence-modules/spring-hibernate4/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/spring-hibernate4/README.md b/persistence-modules/spring-hibernate4/README.md index 57a341ed45..c6d846a18d 100644 --- a/persistence-modules/spring-hibernate4/README.md +++ b/persistence-modules/spring-hibernate4/README.md @@ -3,7 +3,7 @@ ## Spring with Hibernate 4 Example Project ### Relevant Articles: -- [Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring) +- [Guide to Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring) - [The DAO with Spring 3 and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate) - [Hibernate Pagination](http://www.baeldung.com/hibernate-pagination) - [Sorting with Hibernate](http://www.baeldung.com/hibernate-sort) From e3ba00d4fdd6fdfada6b38dae2c17fdc26b11c8f Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 21:01:26 +0800 Subject: [PATCH 174/496] Update README.md --- persistence-modules/spring-hibernate4/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/spring-hibernate4/README.md b/persistence-modules/spring-hibernate4/README.md index c6d846a18d..f2553ad229 100644 --- a/persistence-modules/spring-hibernate4/README.md +++ b/persistence-modules/spring-hibernate4/README.md @@ -4,7 +4,7 @@ ### Relevant Articles: - [Guide to Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring) -- [The DAO with Spring 3 and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate) +- [The DAO with Spring and Hibernate](http://www.baeldung.com/persistence-layer-with-spring-and-hibernate) - [Hibernate Pagination](http://www.baeldung.com/hibernate-pagination) - [Sorting with Hibernate](http://www.baeldung.com/hibernate-sort) - [Stored Procedures with Hibernate](http://www.baeldung.com/stored-procedures-with-hibernate-tutorial) From 60d198882476d3579693929fad8e4755c94d4cfd Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 21:05:52 +0800 Subject: [PATCH 175/496] Update README.md --- core-java-lang-syntax/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-lang-syntax/README.md b/core-java-lang-syntax/README.md index e77a8a58cb..81c3d6c354 100644 --- a/core-java-lang-syntax/README.md +++ b/core-java-lang-syntax/README.md @@ -8,7 +8,7 @@ - [Java Double Brace Initialization](http://www.baeldung.com/java-double-brace-initialization) - [Guide to the Diamond Operator in Java](http://www.baeldung.com/java-diamond-operator) - [The Java continue and break Keywords](http://www.baeldung.com/java-continue-and-break) -- [A Guide to Java Initialization](http://www.baeldung.com/java-initialization) +- [A Guide to Creating Objects in Java](http://www.baeldung.com/java-initialization) - [A Guide to Java Loops](http://www.baeldung.com/java-loops) - [Varargs in Java](http://www.baeldung.com/java-varargs) - [A Guide to Java Enums](http://www.baeldung.com/a-guide-to-java-enums) From d7c44430102f40540414b1941c43f3af69e4d688 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 21:15:55 +0800 Subject: [PATCH 176/496] Update README.md --- testing-modules/junit-5/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md index e68d72efe3..abd50261e7 100644 --- a/testing-modules/junit-5/README.md +++ b/testing-modules/junit-5/README.md @@ -8,7 +8,7 @@ - [Mockito and JUnit 5 – Using ExtendWith](http://www.baeldung.com/mockito-junit-5-extension) - [JUnit 5 – @RunWith](http://www.baeldung.com/junit-5-runwith) - [JUnit 5 @Test Annotation](http://www.baeldung.com/junit-5-test-annotation) -- [JUnit Assert an Exception is Thrown](http://www.baeldung.com/junit-assert-exception) +- [Assert an Exception is Thrown in JUnit 4 and 5](http://www.baeldung.com/junit-assert-exception) - [@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll](http://www.baeldung.com/junit-before-beforeclass-beforeeach-beforeall) - [Migrating from JUnit 4 to JUnit 5](http://www.baeldung.com/junit-5-migration) - [JUnit5 Programmatic Extension Registration with @RegisterExtension](http://www.baeldung.com/junit-5-registerextension-annotation) From ffc06440554a22eae0e94634695168831c9ec979 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 21:17:44 +0800 Subject: [PATCH 177/496] Update README.md --- spring-all/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-all/README.md b/spring-all/README.md index 6e392088d9..81dd435007 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -28,7 +28,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Model, ModelMap, and ModelView in Spring MVC](http://www.baeldung.com/spring-mvc-model-model-map-model-view) - [A Guide To Caching in Spring](http://www.baeldung.com/spring-cache-tutorial) - [How To Do @Async in Spring](http://www.baeldung.com/spring-async) -- [Quick Guide to the Spring @Order Annotation](http://www.baeldung.com/spring-order) +- [@Order in Spring](http://www.baeldung.com/spring-order) - [Spring Web Contexts](http://www.baeldung.com/spring-web-contexts) - [Spring Cache – Creating a Custom KeyGenerator](http://www.baeldung.com/spring-cache-custom-keygenerator) - [Spring @Primary Annotation](http://www.baeldung.com/spring-primary) From 1e8cc42e2072f0a39e77e4b8d7031120ff4f26b6 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 21:20:04 +0800 Subject: [PATCH 178/496] Update README.md --- java-strings/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-strings/README.md b/java-strings/README.md index 1ab5e098f6..fc9748cd2c 100644 --- a/java-strings/README.md +++ b/java-strings/README.md @@ -22,7 +22,7 @@ - [Check if a String is a Palindrome](http://www.baeldung.com/java-palindrome) - [Comparing Strings in Java](http://www.baeldung.com/java-compare-strings) - [Check If a String Is Numeric in Java](http://www.baeldung.com/java-check-string-number) -- [Why Use char[] Array Over a String for Storing Passwords in Java?](http://www.baeldung.com/java-storing-passwords) +- [Use char[] Array Over a String for Manipulating Passwords in Java?](http://www.baeldung.com/java-storing-passwords) - [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case) - [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string) - [Java Check a String for Lowercase/Uppercase Letter, Special Character and Digit](https://www.baeldung.com/java-lowercase-uppercase-special-character-digit-regex) From df9935ce979d952bf2c5e8be4de5a95853698f82 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 21:22:25 +0800 Subject: [PATCH 179/496] Update README.md --- persistence-modules/hibernate5/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/hibernate5/README.md b/persistence-modules/hibernate5/README.md index a4e95a9062..b7f2cd8387 100644 --- a/persistence-modules/hibernate5/README.md +++ b/persistence-modules/hibernate5/README.md @@ -18,7 +18,7 @@ - [@JoinColumn Annotation Explained](https://www.baeldung.com/jpa-join-column) - [Hibernate 5 Naming Strategy Configuration](https://www.baeldung.com/hibernate-naming-strategy) - [Proxy in Hibernate load() Method](https://www.baeldung.com/hibernate-proxy-load-method) -- [Custom Types in Hibernate](https://www.baeldung.com/hibernate-custom-types) +- [Custom Types in Hibernate and the @Type Annotation](https://www.baeldung.com/hibernate-custom-types) - [Criteria API – An Example of IN Expressions](https://www.baeldung.com/jpa-criteria-api-in-expressions) - [Difference Between @JoinColumn and mappedBy](https://www.baeldung.com/jpa-joincolumn-vs-mappedby) - [Hibernate 5 Bootstrapping API](https://www.baeldung.com/hibernate-5-bootstrapping-api) From a98105f3d06da02aeb2df0adda87ea291651d07f Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Thu, 28 Feb 2019 19:02:35 +0530 Subject: [PATCH 180/496] BAEL-12770 Aligned artifactid and name of jhipster-microservice-uaa to jhipster-uaa --- jhipster/jhipster-uaa/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jhipster/jhipster-uaa/pom.xml b/jhipster/jhipster-uaa/pom.xml index 2c890c7b41..a59b19d1fd 100644 --- a/jhipster/jhipster-uaa/pom.xml +++ b/jhipster/jhipster-uaa/pom.xml @@ -2,8 +2,8 @@ 4.0.0 - jhipster-microservice-uaa - jhipster-microservice-uaa + jhipster-uaa + jhipster-uaa pom From ee475e09d703591f8262941de6ebd6ef4540f7d0 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Feb 2019 21:54:27 +0800 Subject: [PATCH 181/496] Update README.md --- spring-boot-bootstrap/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-bootstrap/README.md b/spring-boot-bootstrap/README.md index 2186aa8fec..70fcd90118 100644 --- a/spring-boot-bootstrap/README.md +++ b/spring-boot-bootstrap/README.md @@ -1,5 +1,5 @@ ### Relevant Articles: -- [Bootstrap a Simple Application using Spring Boot](http://www.baeldung.com/spring-boot-start) +- [Spring Boot Tutorial – Bootstrap a Simple Application](http://www.baeldung.com/spring-boot-start) - [Spring Boot Dependency Management with a Custom Parent](http://www.baeldung.com/spring-boot-dependency-management-custom-parent) - [Thin JARs with Spring Boot](http://www.baeldung.com/spring-boot-thin-jar) - [Deploying a Spring Boot Application to Cloud Foundry](https://www.baeldung.com/spring-boot-app-deploy-to-cloud-foundry) From d62fd333b0b8f6a0eb953d6b7720093f3b58b977 Mon Sep 17 00:00:00 2001 From: Jonathan Paul Cook Date: Thu, 28 Feb 2019 17:09:00 +0100 Subject: [PATCH 182/496] BAEL-2512 - Add a new section in Mockito Spy article --- .../misusing/MockitoMisusingUnitTest.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java diff --git a/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java new file mode 100644 index 0000000000..e2de23aa14 --- /dev/null +++ b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java @@ -0,0 +1,30 @@ +package org.baeldung.mockito.misusing; + +import static org.hamcrest.core.StringContains.containsString; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.exceptions.misusing.NotAMockException; + +public class MockitoMisusingUnitTest { + + @Test + public void givenNotASpy_whenDoReturn_thenThrowNotAMock() { + try { + List list = new ArrayList(); + Mockito.doReturn(100) + .when(list) + .size(); + + fail("Should have thrown a NotAMockException because 'list' is not a mock!"); + } catch (NotAMockException e) { + assertThat(e.getMessage(), containsString("Argument passed to when() is not a mock!")); + } + } + +} From f067f5a0f5f254ec919c09b6d0a851abc0ebffaa Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Thu, 28 Feb 2019 22:15:51 +0530 Subject: [PATCH 183/496] BAEL-10890 Added aggregator poms in several projects, cleaned up main pom.xml --- cas/pom.xml | 21 ++++ guava-modules/pom.xml | 22 ++++ logging-modules/pom.xml | 23 ++++ persistence-modules/pom.xml | 58 ++++++++++ pom.xml | 198 ++++----------------------------- rule-engines/pom.xml | 22 ++++ spring-security-client/pom.xml | 25 +++++ testing-modules/pom.xml | 36 ++++++ 8 files changed, 230 insertions(+), 175 deletions(-) create mode 100644 cas/pom.xml create mode 100644 guava-modules/pom.xml create mode 100644 logging-modules/pom.xml create mode 100644 persistence-modules/pom.xml create mode 100644 rule-engines/pom.xml create mode 100644 spring-security-client/pom.xml create mode 100644 testing-modules/pom.xml diff --git a/cas/pom.xml b/cas/pom.xml new file mode 100644 index 0000000000..ac766ae5bf --- /dev/null +++ b/cas/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + cas + cas + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + cas-secured-app + cas-server + + + diff --git a/guava-modules/pom.xml b/guava-modules/pom.xml new file mode 100644 index 0000000000..7a5f217c15 --- /dev/null +++ b/guava-modules/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + guava-modules + guava-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + guava-18 + guava-19 + guava-21 + + + diff --git a/logging-modules/pom.xml b/logging-modules/pom.xml new file mode 100644 index 0000000000..d48955b1b8 --- /dev/null +++ b/logging-modules/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + logging-modules + logging-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + log4j + log4j2 + logback + log-mdc + + + diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml new file mode 100644 index 0000000000..beba135d7f --- /dev/null +++ b/persistence-modules/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + persistence-modules + persistence-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + activejdbc + apache-cayenne + core-java-persistence + deltaspike + flyway + hbase + hibernate5 + hibernate-ogm + influxdb + java-cassandra + java-cockroachdb + java-jdbi + java-jpa + java-mongodb + jnosql + liquibase + orientdb + querydsl + redis + solr + spring-boot-h2/spring-boot-h2-database + spring-boot-persistence + spring-boot-persistence-mongodb + spring-data-cassandra + spring-data-cassandra-reactive + spring-data-couchbase-2 + spring-data-dynamodb + spring-data-eclipselink + spring-data-elasticsearch + spring-data-gemfire + spring-data-jpa + spring-data-keyvalue + spring-data-mongodb + spring-data-neo4j + spring-data-redis + spring-data-solr + spring-hibernate-3 + spring-hibernate-5 + spring-hibernate4 + spring-jpa + + diff --git a/pom.xml b/pom.xml index 0a401299ba..d26b96ea8e 100644 --- a/pom.xml +++ b/pom.xml @@ -371,8 +371,7 @@ bootique - cas/cas-secured-app - cas/cas-server + cas cdi checker-plugin core-groovy @@ -422,9 +421,7 @@ gson guava guava-collections - guava-modules/guava-18 - guava-modules/guava-19 - guava-modules/guava-21 + guava-modules guice @@ -475,16 +472,13 @@ kotlin-libraries - libraries + libraries libraries-data libraries-apache-commons libraries-security libraries-server linkrest - logging-modules/log4j - logging-modules/log4j2 - logging-modules/logback - logging-modules/log-mdc + logging-modules lombok lucene @@ -515,45 +509,7 @@ protobuffer - persistence-modules/activejdbc - persistence-modules/apache-cayenne - persistence-modules/core-java-persistence - persistence-modules/deltaspike - persistence-modules/flyway - persistence-modules/hbase - persistence-modules/hibernate5 - persistence-modules/hibernate-ogm - persistence-modules/influxdb - persistence-modules/java-cassandra - persistence-modules/java-cockroachdb - persistence-modules/java-jdbi - persistence-modules/java-jpa - persistence-modules/jnosql - persistence-modules/liquibase - persistence-modules/orientdb - persistence-modules/querydsl - persistence-modules/redis - persistence-modules/solr - persistence-modules/spring-boot-h2/spring-boot-h2-database - persistence-modules/spring-boot-persistence - persistence-modules/spring-boot-persistence-mongodb - persistence-modules/spring-data-cassandra - persistence-modules/spring-data-cassandra-reactive - persistence-modules/spring-data-couchbase-2 - persistence-modules/spring-data-dynamodb - persistence-modules/spring-data-eclipselink - persistence-modules/spring-data-elasticsearch - persistence-modules/spring-data-gemfire - persistence-modules/spring-data-jpa - persistence-modules/spring-data-keyvalue - persistence-modules/spring-data-mongodb - persistence-modules/spring-data-neo4j - persistence-modules/spring-data-redis - persistence-modules/spring-data-solr - persistence-modules/spring-hibernate-3 - persistence-modules/spring-hibernate-5 - persistence-modules/spring-hibernate4 - persistence-modules/spring-jpa + persistence-modules rabbitmq @@ -563,9 +519,7 @@ resteasy restx - rule-engines/easy-rules - rule-engines/openl-tablets - rule-engines/rulebook + rule-engines rsocket rxjava rxjava-2 @@ -721,13 +675,7 @@ spring-security-angular/server spring-security-cache-control - spring-security-client/spring-security-jsp-authentication - spring-security-client/spring-security-jsp-authorize - spring-security-client/spring-security-jsp-config - spring-security-client/spring-security-mvc - spring-security-client/spring-security-thymeleaf-authentication - spring-security-client/spring-security-thymeleaf-authorize - spring-security-client/spring-security-thymeleaf-config + spring-security-client spring-security-core spring-security-mvc-boot @@ -773,24 +721,7 @@ structurizr struts-2 - testing-modules/gatling - testing-modules/groovy-spock - testing-modules/junit-5 - testing-modules/junit5-migration - testing-modules/load-testing-comparison - testing-modules/mockito - testing-modules/mockito-2 - testing-modules/mocks - testing-modules/mockserver - testing-modules/parallel-tests-junit - testing-modules/rest-assured - testing-modules/rest-testing - - testing-modules/selenium-junit-testng - testing-modules/spring-testing - testing-modules/test-containers - testing-modules/testing - testing-modules/testng + testing-modules twilio Twitter4J @@ -849,8 +780,7 @@ spring-apache-camel spring-batch spring-bom - spring-boot-admin/spring-boot-admin-client - spring-boot-admin/spring-boot-admin-server + spring-boot-admin spring-boot-bootstrap spring-boot-bootstrap spring-boot-camel @@ -862,22 +792,18 @@ spring-boot-jasypt spring-boot-keycloak spring-boot-mvc - spring-boot-property-exp/property-exp-custom-config - spring-boot-property-exp/property-exp-default-config + spring-boot-property-exp spring-boot-vue spring-cloud spring-cloud/spring-cloud-archaius/basic-config spring-cloud/spring-cloud-archaius/extra-configs spring-cloud/spring-cloud-bootstrap/config - spring-cloud/spring-cloud-contract/spring-cloud-contract-consumer - spring-cloud/spring-cloud-contract/spring-cloud-contract-producer + spring-cloud/spring-cloud-contract spring-cloud/spring-cloud-gateway spring-cloud/spring-cloud-kubernetes/demo-backend spring-cloud/spring-cloud-rest/spring-cloud-rest-config-server spring-cloud/spring-cloud-ribbon-client - spring-cloud/spring-cloud-security/auth-client - spring-cloud/spring-cloud-security/auth-resource - spring-cloud/spring-cloud-security/auth-server + spring-cloud/spring-cloud-security spring-cloud/spring-cloud-stream/spring-cloud-stream-rabbit spring-cloud/spring-cloud-task/springcloudtasksink spring-cloud/spring-cloud-zookeeper @@ -925,13 +851,7 @@ spring-security-acl spring-security-angular spring-security-cache-control - spring-security-client/spring-security-jsp-authentication - spring-security-client/spring-security-jsp-authorize - spring-security-client/spring-security-jsp-config - spring-security-client/spring-security-mvc - spring-security-client/spring-security-thymeleaf-authentication - spring-security-client/spring-security-thymeleaf-authorize - spring-security-client/spring-security-thymeleaf-config + spring-security-client spring-security-core spring-security-mvc-boot spring-security-mvc-custom @@ -941,14 +861,11 @@ spring-security-mvc-session spring-security-mvc-socket spring-security-rest - spring-security-sso/spring-security-sso-auth-server - spring-security-sso/spring-security-sso-ui - spring-security-sso/spring-security-sso-ui-2 + spring-security-sso spring-security-thymeleaf/spring-security-thymeleaf-authentication spring-security-thymeleaf/spring-security-thymeleaf-authorize spring-security-thymeleaf/spring-security-thymeleaf-config - spring-security-x509/spring-security-x509-basic-auth - spring-security-x509/spring-security-x509-client-auth + spring-security-x509 spring-session/spring-session-jdbc spring-sleuth spring-social-login @@ -1090,8 +1007,7 @@ bootique - cas/cas-secured-app - cas/cas-server + cas cdi checker-plugin core-groovy @@ -1140,9 +1056,7 @@ gson guava guava-collections - guava-modules/guava-18 - guava-modules/guava-19 - guava-modules/guava-21 + guava-modules guice @@ -1199,10 +1113,7 @@ libraries-security libraries-server linkrest - logging-modules/log4j - logging-modules/log4j2 - logging-modules/logback - logging-modules/log-mdc + logging-modules lombok lucene @@ -1233,46 +1144,8 @@ protobuffer - persistence-modules/activejdbc - persistence-modules/apache-cayenne - persistence-modules/core-java-persistence - persistence-modules/deltaspike - persistence-modules/flyway - persistence-modules/hbase - persistence-modules/hibernate5 - persistence-modules/hibernate-ogm - persistence-modules/influxdb - persistence-modules/java-cassandra - persistence-modules/java-cockroachdb - persistence-modules/java-jdbi - persistence-modules/java-jpa - persistence-modules/jnosql - persistence-modules/liquibase - persistence-modules/orientdb - persistence-modules/querydsl - persistence-modules/redis - persistence-modules/solr - persistence-modules/spring-boot-h2/spring-boot-h2-database - persistence-modules/spring-boot-persistence - persistence-modules/spring-boot-persistence-mongodb - persistence-modules/spring-data-cassandra - persistence-modules/spring-data-cassandra-reactive - persistence-modules/spring-data-couchbase-2 - persistence-modules/spring-data-dynamodb - persistence-modules/spring-data-eclipselink - persistence-modules/spring-data-elasticsearch - persistence-modules/spring-data-gemfire - persistence-modules/spring-data-jpa - persistence-modules/spring-data-keyvalue - persistence-modules/spring-data-mongodb - persistence-modules/spring-data-neo4j - persistence-modules/spring-data-redis - persistence-modules/spring-data-solr - persistence-modules/spring-hibernate-3 - persistence-modules/spring-hibernate-5 - persistence-modules/spring-hibernate4 - persistence-modules/spring-jpa - + persistence-modules + rabbitmq ratpack @@ -1281,9 +1154,7 @@ resteasy restx - rule-engines/easy-rules - rule-engines/openl-tablets - rule-engines/rulebook + rule-engines rsocket rxjava rxjava-2 @@ -1434,13 +1305,7 @@ spring-security-angular/server spring-security-cache-control - spring-security-client/spring-security-jsp-authentication - spring-security-client/spring-security-jsp-authorize - spring-security-client/spring-security-jsp-config - spring-security-client/spring-security-mvc - spring-security-client/spring-security-thymeleaf-authentication - spring-security-client/spring-security-thymeleaf-authorize - spring-security-client/spring-security-thymeleaf-config + spring-security-client spring-security-core spring-security-mvc-boot @@ -1485,24 +1350,7 @@ structurizr struts-2 - testing-modules/gatling - testing-modules/groovy-spock - testing-modules/junit-5 - testing-modules/junit5-migration - testing-modules/load-testing-comparison - testing-modules/mockito - testing-modules/mockito-2 - testing-modules/mocks - testing-modules/mockserver - testing-modules/parallel-tests-junit - testing-modules/rest-assured - testing-modules/rest-testing - - testing-modules/selenium-junit-testng - testing-modules/spring-testing - testing-modules/test-containers - testing-modules/testing - testing-modules/testng + testing-modules twilio Twitter4J diff --git a/rule-engines/pom.xml b/rule-engines/pom.xml new file mode 100644 index 0000000000..2b3f2f530b --- /dev/null +++ b/rule-engines/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + rule-engines + rule-engines + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + easy-rules + openl-tablets + rulebook + + + diff --git a/spring-security-client/pom.xml b/spring-security-client/pom.xml new file mode 100644 index 0000000000..aa424ca759 --- /dev/null +++ b/spring-security-client/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + spring-security-client + spring-security-client + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + spring-security-jsp-authentication + spring-security-jsp-authorize + spring-security-jsp-config + spring-security-mvc + spring-security-thymeleaf-authentication + spring-security-thymeleaf-authorize + spring-security-thymeleaf-config + + diff --git a/testing-modules/pom.xml b/testing-modules/pom.xml new file mode 100644 index 0000000000..6a3c2399f8 --- /dev/null +++ b/testing-modules/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + testing-modules + testing-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + .. + + + + gatling + groovy-spock + junit-5 + junit5-migration + load-testing-comparison + mockito + mockito-2 + mocks + mockserver + parallel-tests-junit + rest-assured + rest-testing + + selenium-junit-testng + spring-testing + test-containers + testing + testng + + From a2f1f59e1f3cae524892ed515dcfee58bc543bab Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Thu, 28 Feb 2019 22:21:29 +0530 Subject: [PATCH 184/496] BAEL-10890 Fixed minor formatting --- cas/pom.xml | 2 +- guava-modules/pom.xml | 4 ++-- logging-modules/pom.xml | 6 +++--- persistence-modules/pom.xml | 2 +- rule-engines/pom.xml | 4 ++-- spring-security-client/pom.xml | 2 +- testing-modules/pom.xml | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cas/pom.xml b/cas/pom.xml index ac766ae5bf..6d141277c5 100644 --- a/cas/pom.xml +++ b/cas/pom.xml @@ -15,7 +15,7 @@ cas-secured-app - cas-server + cas-server diff --git a/guava-modules/pom.xml b/guava-modules/pom.xml index 7a5f217c15..fed9e446f7 100644 --- a/guava-modules/pom.xml +++ b/guava-modules/pom.xml @@ -15,8 +15,8 @@ guava-18 - guava-19 - guava-21 + guava-19 + guava-21 diff --git a/logging-modules/pom.xml b/logging-modules/pom.xml index d48955b1b8..a303e50ff1 100644 --- a/logging-modules/pom.xml +++ b/logging-modules/pom.xml @@ -15,9 +15,9 @@ log4j - log4j2 - logback - log-mdc + log4j2 + logback + log-mdc diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index beba135d7f..47c733d8a7 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -54,5 +54,5 @@ spring-hibernate-5 spring-hibernate4 spring-jpa - + diff --git a/rule-engines/pom.xml b/rule-engines/pom.xml index 2b3f2f530b..2ce82ed22b 100644 --- a/rule-engines/pom.xml +++ b/rule-engines/pom.xml @@ -15,8 +15,8 @@ easy-rules - openl-tablets - rulebook + openl-tablets + rulebook diff --git a/spring-security-client/pom.xml b/spring-security-client/pom.xml index aa424ca759..96ac837a09 100644 --- a/spring-security-client/pom.xml +++ b/spring-security-client/pom.xml @@ -21,5 +21,5 @@ spring-security-thymeleaf-authentication spring-security-thymeleaf-authorize spring-security-thymeleaf-config - + diff --git a/testing-modules/pom.xml b/testing-modules/pom.xml index 6a3c2399f8..39047fb756 100644 --- a/testing-modules/pom.xml +++ b/testing-modules/pom.xml @@ -32,5 +32,5 @@ test-containers testing testng - + From d753bd3bd39a4256362d8ce4fdca7fecb895fa19 Mon Sep 17 00:00:00 2001 From: Josephine Barboza Date: Thu, 28 Feb 2019 22:57:01 +0530 Subject: [PATCH 185/496] BAEL-2725 Lists in Groovy --- .../groovy/com/baeldung/lists/ListTest.groovy | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy diff --git a/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy new file mode 100644 index 0000000000..89a0194742 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy @@ -0,0 +1,170 @@ +package com.baeldung.groovy.lists + +import static groovy.test.GroovyAssert.* +import org.junit.Test + +class ListTest{ + + @Test + void testCreateList() { + + def list = [1, 2, 3] + assertNotNull(list) + + def listMix = ['A', "b", 1, true] + assertTrue(listMix == ['A', "b", 1, true]) + + def linkedList = [1, 2, 3] as LinkedList + assertTrue(linkedList instanceof LinkedList) + + ArrayList arrList = [1, 2, 3] + assertTrue(arrList.class == ArrayList) + + def list2 = new ArrayList(arrList) + assertTrue(list2 == arrList) + + def list3 = arrList.clone() + assertTrue(list3 == arrList) + } + + @Test + void testCreateEmptyList() { + + def emptyList = [] + assertTrue(emptyList.size() == 0) + } + + @Test + void testCompareTwoLists() { + + def list1 = [5, 6.0, 'p'] + def list2 = [5, 6.0, 'p'] + assertTrue(list1 == list2) + } + + @Test + void testGetItemsFromList(){ + + def list = ["Hello", "World"] + + assertTrue(list.get(1) == "World") + assertTrue(list[1] == "World") + assertTrue(list[-1] == "World") + assertTrue(list.getAt(1) == "World") + assertTrue(list.getAt(-2) == "Hello") + } + + @Test + void testAddItemsToList() { + + def list = [] + + list << 1 + list.add("Apple") + assertTrue(list == [1, "Apple"]) + + list[2] = "Box" + list[4] = true + assertTrue(list == [1, "Apple", "Box", null, true]) + + list.add(1, 6.0) + assertTrue(list == [1, 6.0, "Apple", "Box", null, true]) + + def list2 = [1, 2] + list += list2 + list += 12 + assertTrue(list == [1, 6.0, "Apple", "Box", null, true, 1, 2, 12]) + } + + @Test + void testUpdateItemsInList() { + + def list =[1, "Apple", 80, "App"] + list[1] = "Box" + list.set(2,90) + assertTrue(list == [1, "Box", 90, "App"]) + } + + @Test + void testRemoveItemsFromList(){ + + def list = [1, 2, 3, 4, 5, 5, 6, 6, 7] + + list.remove(3) + assertTrue(list == [1, 2, 3, 5, 5, 6, 6, 7]) + + list.removeElement(5) + assertTrue(list == [1, 2, 3, 5, 6, 6, 7]) + + assertTrue(list - 6 == [1, 2, 3, 5, 7]) + } + + @Test + void testIteratingOnAList(){ + + def list = [1, "App", 3, 4] + list.each{ println it * 2} + + list.eachWithIndex{ it, i -> println "$i : $it" } + } + + @Test + void testCollectingToAnotherList(){ + + def list = ["Kay", "Henry", "Justin", "Tom"] + assertTrue(list.collect{"Hi " + it} == ["Hi Kay", "Hi Henry", "Hi Justin", "Hi Tom"]) + } + + @Test + void testJoinItemsInAList(){ + assertTrue(["One", "Two", "Three"].join(",") == "One,Two,Three") + } + + @Test + void testFilteringOnLists(){ + def list = [2, 1, 3, 4, 5, 6, 76] + + assertTrue(list.find{it > 3} == 4) + + assertTrue(list.findAll{it > 3} == [4, 5, 6, 76]) + + assertTrue(list.findAll{ it instanceof Number} == [2, 1, 3, 4, 5, 6, 76]) + + assertFalse(list.every{ it < 6}) + + assertTrue(list.any{ it%2 == 0}) + + assertTrue(list.grep( Number )== [2, 1, 3, 4, 5, 6, 76]) + + assertTrue(list.grep{ it> 6 }== [76]) + } + + @Test + void testGetUniqueItemsInAList(){ + assertTrue([1, 3, 3, 4].toUnique() == [1, 3, 4]) + + def list = [1, 3, 3, 4] + list.unique() + assertTrue(list == [1, 3, 4]) + + assertTrue(["A", "B", "Ba", "Bat", "Cat"].toUnique{ it.size()} == ["A", "Ba", "Bat"]) + } + + @Test + void testSorting(){ + + assertTrue([1, 2, 1, 0].sort() == [0, 1, 1, 2]) + Comparator mc = {a,b -> a == b? 0: a < b? 1 : -1} + + def list = [1, 2, 1, 0] + list.sort(mc) + assertTrue(list == [2, 1, 1, 0]) + + def list1 = ["na", "ppp", "as"] + assertTrue(list1.max() == "ppp") + + Comparator minc = {a,b -> a == b? 0: a < b? -1 : 1} + def list2 = [3, 2, 0, 7] + assertTrue(list2.min(minc) == 0) + } +} \ No newline at end of file From 455c831b059780b560dae661c9dc726119463995 Mon Sep 17 00:00:00 2001 From: Upendra Chintala Date: Fri, 1 Mar 2019 00:32:41 +0530 Subject: [PATCH 186/496] An example program to make JSON Post request with HttpURLConnection (#6415) * An example program to make JSON Post request with HttpURLConnection * Made few changes for better readability --- .../PostJSONWithHttpURLConnection.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/urlconnection/PostJSONWithHttpURLConnection.java diff --git a/core-java/src/main/java/com/baeldung/urlconnection/PostJSONWithHttpURLConnection.java b/core-java/src/main/java/com/baeldung/urlconnection/PostJSONWithHttpURLConnection.java new file mode 100644 index 0000000000..38b4a0411d --- /dev/null +++ b/core-java/src/main/java/com/baeldung/urlconnection/PostJSONWithHttpURLConnection.java @@ -0,0 +1,46 @@ +package com.baeldung.urlconnection; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class PostJSONWithHttpURLConnection { + + public static void main (String []args) throws IOException{ + //Change the URL with any other publicly accessible POST resource, which accepts JSON request body + URL url = new URL ("https://reqres.in/api/users"); + + HttpURLConnection con = (HttpURLConnection)url.openConnection(); + con.setRequestMethod("POST"); + + con.setRequestProperty("Content-Type", "application/json; utf-8"); + con.setRequestProperty("Accept", "application/json"); + + con.setDoOutput(true); + + //JSON String need to be constructed for the specific resource. + //We may construct complex JSON using any third-party JSON libraries such as jackson or org.json + String jsonInputString = "{\"name\": \"Upendra\", \"job\": \"Programmer\"}"; + + try(OutputStream os = con.getOutputStream()){ + byte[] input = jsonInputString.getBytes("utf-8"); + os.write(input, 0, input.length); + } + + int code = con.getResponseCode(); + System.out.println(code); + + try(BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"))){ + StringBuilder response = new StringBuilder(); + String responseLine = null; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + System.out.println(response.toString()); + } + } + +} From 725a6e04d55f30ebf71aa65b3f8e4019be88439b Mon Sep 17 00:00:00 2001 From: Andrea Ligios Date: Fri, 1 Mar 2019 07:20:10 +0100 Subject: [PATCH 187/496] BAEL-2667 (#6442) --- core-groovy/pom.xml | 15 ++++- .../groovy/com/baeldung/date/DateTest.groovy | 57 +++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 core-groovy/src/test/groovy/com/baeldung/date/DateTest.groovy diff --git a/core-groovy/pom.xml b/core-groovy/pom.xml index e54c766280..029e5460ab 100644 --- a/core-groovy/pom.xml +++ b/core-groovy/pom.xml @@ -23,6 +23,12 @@ org.codehaus.groovy groovy-all ${groovy-all.version} + pom + + + org.codehaus.groovy + groovy-dateutil + ${groovy.version} org.codehaus.groovy @@ -103,9 +109,12 @@ 1.0.0 - 2.4.13 - 2.4.13 - 2.4.13 + + + + 2.5.6 + 2.5.6 + 2.5.6 2.4.0 1.1-groovy-2.4 1.6 diff --git a/core-groovy/src/test/groovy/com/baeldung/date/DateTest.groovy b/core-groovy/src/test/groovy/com/baeldung/date/DateTest.groovy new file mode 100644 index 0000000000..4e7a7189a6 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/date/DateTest.groovy @@ -0,0 +1,57 @@ +package com.baeldung.groovy.sql + +import static org.junit.Assert.* +import java.util.Calendar.* +import java.time.LocalDate +import java.text.SimpleDateFormat +import org.junit.Test + + +class DateTest { + + def dateStr = "2019-02-28" + def pattern = "yyyy-MM-dd" + + @Test + void whenGetStringRepresentation_thenCorrectlyConvertIntoDate() { + def dateFormat = new SimpleDateFormat(pattern) + def date = dateFormat.parse(dateStr) + + println(" String to Date with DateFormatter : " + date) + + def cal = new GregorianCalendar(); + cal.setTime(date); + + assertEquals(cal.get(Calendar.YEAR),2019) + assertEquals(cal.get(Calendar.DAY_OF_MONTH),28) + assertEquals(cal.get(Calendar.MONTH),java.util.Calendar.FEBRUARY) + } + + @Test + void whenGetStringRepresentation_thenCorrectlyConvertWithDateUtilsExtension() { + + def date = Date.parse(pattern, dateStr) + + println(" String to Date with Date.parse : " + date) + + def cal = new GregorianCalendar(); + cal.setTime(date); + + assertEquals(cal.get(Calendar.YEAR),2019) + assertEquals(cal.get(Calendar.DAY_OF_MONTH),28) + assertEquals(cal.get(Calendar.MONTH),java.util.Calendar.FEBRUARY) + } + + @Test + void whenGetStringRepresentation_thenCorrectlyConvertIntoDateWithLocalDate() { + def date = LocalDate.parse(dateStr, pattern) + + println(" String to Date with LocalDate : " + date) + + assertEquals(date.getYear(),2019) + assertEquals(date.getMonth(),java.time.Month.FEBRUARY) + assertEquals(date.getDayOfMonth(),28) + } + + +} From 23010dd32a5e88c095bcb2048dd113b7aced7a42 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Fri, 1 Mar 2019 18:40:44 +0800 Subject: [PATCH 188/496] Update README.md --- core-java-networking/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-networking/README.md b/core-java-networking/README.md index f6ce44d72f..faeeadab24 100644 --- a/core-java-networking/README.md +++ b/core-java-networking/README.md @@ -9,7 +9,7 @@ - [A Guide To UDP In Java](http://www.baeldung.com/udp-in-java) - [Sending Emails with Java](http://www.baeldung.com/java-email) - [A Guide To HTTP Cookies In Java](http://www.baeldung.com/cookies-java) -- [A Guide to the Java URL](http://www.baeldung.com/java-url) +- [A Simple Guide to the Java URL](http://www.baeldung.com/java-url) - [Working with Network Interfaces in Java](http://www.baeldung.com/java-network-interfaces) - [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets) - [Guide to Java URL Encoding/Decoding](http://www.baeldung.com/java-url-encoding-decoding) From 6189d4645e8d0ee3799080c7d8e06c2c1a08b3f0 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Fri, 1 Mar 2019 18:43:45 +0800 Subject: [PATCH 189/496] Update README.md --- spring-remoting/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-remoting/README.md b/spring-remoting/README.md index 7d344a3f27..0898b9b002 100644 --- a/spring-remoting/README.md +++ b/spring-remoting/README.md @@ -4,7 +4,7 @@ - [Intro to Spring Remoting with HTTP Invokers](http://www.baeldung.com/spring-remoting-http-invoker) - [Spring Remoting with Hessian and Burlap](http://www.baeldung.com/spring-remoting-hessian-burlap) - [Spring Remoting with AMQP](http://www.baeldung.com/spring-remoting-amqp) -- [Spring Remoting with JMS](http://www.baeldung.com/spring-remoting-jms) +- [Spring Remoting with JMS and ActiveMQ](http://www.baeldung.com/spring-remoting-jms) - [Spring Remoting with RMI](http://www.baeldung.com/spring-remoting-rmi) ### Overview From bb4258a0daa94633795987d73d2cfac4c1135a44 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Fri, 1 Mar 2019 18:44:51 +0800 Subject: [PATCH 190/496] Update README.md --- jackson/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jackson/README.md b/jackson/README.md index 519673738f..25194c7255 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -25,7 +25,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [More Jackson Annotations](http://www.baeldung.com/jackson-advanced-annotations) - [Inheritance with Jackson](http://www.baeldung.com/jackson-inheritance) - [Guide to @JsonFormat in Jackson](http://www.baeldung.com/jackson-jsonformat) -- [A Guide to Optional with Jackson](http://www.baeldung.com/jackson-optional) +- [Using Optional with Jackson](http://www.baeldung.com/jackson-optional) - [Map Serialization and Deserialization with Jackson](http://www.baeldung.com/jackson-map) - [Jackson Streaming API](http://www.baeldung.com/jackson-streaming-api) - [Jackson – JsonMappingException (No serializer found for class)](http://www.baeldung.com/jackson-jsonmappingexception) From b577e94b5c5222bc87482d8d2cd02d2c8142fb55 Mon Sep 17 00:00:00 2001 From: Sumeet Gajbhar Date: Sat, 2 Mar 2019 04:55:31 +0530 Subject: [PATCH 191/496] BAEL-2520 code changes done (#6446) --- .../repositories/CustomItemRepository.java | 6 ++ .../impl/CustomItemRepositoryImpl.java | 58 +++++++++++- .../CustomItemRepositoryIntegrationTest.java | 94 +++++++++++++++++++ 3 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryIntegrationTest.java diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemRepository.java index ba077ccf1f..4299f9e3bb 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemRepository.java @@ -1,5 +1,7 @@ package com.baeldung.dao.repositories; +import java.util.List; + import org.springframework.stereotype.Repository; import com.baeldung.domain.Item; @@ -12,4 +14,8 @@ public interface CustomItemRepository { Item findItemById(Long id); void findThenDelete(Long id); + + List findItemsByColorAndGrade(); + + List findItemByColorOrGrade(); } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryImpl.java index 53def88af0..9791cb0aa7 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryImpl.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryImpl.java @@ -1,12 +1,18 @@ package com.baeldung.dao.repositories.impl; +import java.util.List; + import javax.persistence.EntityManager; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; -import com.baeldung.domain.Item; import com.baeldung.dao.repositories.CustomItemRepository; +import com.baeldung.domain.Item; @Repository public class CustomItemRepositoryImpl implements CustomItemRepository { @@ -29,4 +35,54 @@ public class CustomItemRepositoryImpl implements CustomItemRepository { final Item item = entityManager.find(Item.class, id); entityManager.remove(item); } + + @Override + public List findItemsByColorAndGrade() { + + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Item.class); + Root itemRoot = criteriaQuery.from(Item.class); + + Predicate predicateForBlueColor = criteriaBuilder.equal(itemRoot.get("color"), "blue"); + Predicate predicateForRedColor = criteriaBuilder.equal(itemRoot.get("color"), "red"); + Predicate predicateForColor = criteriaBuilder.or(predicateForBlueColor, predicateForRedColor); + + Predicate predicateForGradeA = criteriaBuilder.equal(itemRoot.get("grade"), "A"); + Predicate predicateForGradeB = criteriaBuilder.equal(itemRoot.get("grade"), "B"); + Predicate predicateForGrade = criteriaBuilder.or(predicateForGradeA, predicateForGradeB); + + // final search filter + Predicate finalPredicate = criteriaBuilder.and(predicateForColor, predicateForGrade); + + criteriaQuery.where(finalPredicate); + + List items = entityManager.createQuery(criteriaQuery) + .getResultList(); + return items; + } + + @Override + public List findItemByColorOrGrade() { + + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Item.class); + Root itemRoot = criteriaQuery.from(Item.class); + + Predicate predicateForBlueColor = criteriaBuilder.equal(itemRoot.get("color"), "red"); + Predicate predicateForGradeA = criteriaBuilder.equal(itemRoot.get("grade"), "D"); + Predicate predicateForBlueColorAndGradeA = criteriaBuilder.and(predicateForBlueColor, predicateForGradeA); + + Predicate predicateForRedColor = criteriaBuilder.equal(itemRoot.get("color"), "blue"); + Predicate predicateForGradeB = criteriaBuilder.equal(itemRoot.get("grade"), "B"); + Predicate predicateForRedColorAndGradeB = criteriaBuilder.and(predicateForRedColor, predicateForGradeB); + + // final search filter + Predicate finalPredicate = criteriaBuilder.or(predicateForBlueColorAndGradeA, predicateForRedColorAndGradeB); + + criteriaQuery.where(finalPredicate); + + List items = entityManager.createQuery(criteriaQuery) + .getResultList(); + return items; + } } diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryIntegrationTest.java new file mode 100644 index 0000000000..c5fb7fa25f --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryIntegrationTest.java @@ -0,0 +1,94 @@ +package com.baeldung.dao.repositories.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.util.List; + +import javax.persistence.EntityManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.CollectionUtils; + +import com.baeldung.config.PersistenceConfiguration; +import com.baeldung.config.PersistenceProductConfiguration; +import com.baeldung.config.PersistenceUserConfiguration; +import com.baeldung.dao.repositories.CustomItemRepository; +import com.baeldung.domain.Item; + +@RunWith(SpringRunner.class) +@DataJpaTest(excludeAutoConfiguration = { PersistenceConfiguration.class, PersistenceUserConfiguration.class, PersistenceProductConfiguration.class }) +public class CustomItemRepositoryIntegrationTest { + + @Autowired + CustomItemRepository customItemRepositoryImpl; + + @Autowired + EntityManager entityManager; + + @Before + public void setUp() { + + Item firstItem = new Item(); + firstItem.setColor("blue"); + firstItem.setGrade("C"); + firstItem.setId(10l); + + entityManager.persist(firstItem); + + Item secondItem = new Item(); + secondItem.setColor("red"); + secondItem.setGrade("C"); + secondItem.setId(11l); + + entityManager.persist(secondItem); + + Item thirdItem = new Item(); + thirdItem.setColor("blue"); + thirdItem.setGrade("A"); + thirdItem.setId(12l); + + entityManager.persist(thirdItem); + + Item fourthItem = new Item(); + fourthItem.setColor("red"); + fourthItem.setGrade("D"); + fourthItem.setId(13l); + + entityManager.persist(fourthItem); + } + + @Test + public void givenItems_whenFindItemsByColorAndGrade_thenReturnItems() { + + List items = customItemRepositoryImpl.findItemsByColorAndGrade(); + + assertFalse("No items found", CollectionUtils.isEmpty(items)); + assertEquals("There should be only one item", 1, items.size()); + + Item item = items.get(0); + + assertEquals("this item do not have blue color", "blue", item.getColor()); + assertEquals("this item does not belong to A grade", "A", item.getGrade()); + } + + @Test + public void givenItems_whenFindItemByColorOrGrade_thenReturnItems() { + + List items = customItemRepositoryImpl.findItemByColorOrGrade(); + + assertFalse("No items found", CollectionUtils.isEmpty(items)); + assertEquals("There should be only one item", 1, items.size()); + + Item item = items.get(0); + + assertEquals("this item do not have red color", "red", item.getColor()); + assertEquals("this item does not belong to D grade", "D", item.getGrade()); + } + +} From 1eba9dfc0195b9a3aff28c32680647b6cee7f535 Mon Sep 17 00:00:00 2001 From: Lentini Alfonso Date: Wed, 27 Feb 2019 15:46:22 +0100 Subject: [PATCH 192/496] spring cloud openfeign example implementation --- spring-cloud/spring-cloud-openfeign/pom.xml | 61 +++++++++++++++++++ .../cloud/openfeign/ExampleApplication.java | 16 +++++ .../client/JSONPlaceHolderClient.java | 25 ++++++++ .../openfeign/config/ClientConfiguration.java | 37 +++++++++++ .../openfeign/config/CustomErrorDecoder.java | 21 +++++++ .../exception/BadRequestException.java | 21 +++++++ .../exception/NotFoundException.java | 21 +++++++ .../hystrix/JSONPlaceHolderFallback.java | 22 +++++++ .../baeldung/cloud/openfeign/model/Post.java | 41 +++++++++++++ .../service/JSONPlaceHolderService.java | 12 ++++ .../impl/JSONPlaceHolderServiceImpl.java | 26 ++++++++ .../src/main/resources/application.properties | 3 + .../cloud/openfeign/OpenfeignUnitTest.java | 43 +++++++++++++ 13 files changed, 349 insertions(+) create mode 100644 spring-cloud/spring-cloud-openfeign/pom.xml create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/ExampleApplication.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/JSONPlaceHolderClient.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/CustomErrorDecoder.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/BadRequestException.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/NotFoundException.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/hystrix/JSONPlaceHolderFallback.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Post.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/JSONPlaceHolderService.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/impl/JSONPlaceHolderServiceImpl.java create mode 100644 spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties create mode 100644 spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignUnitTest.java diff --git a/spring-cloud/spring-cloud-openfeign/pom.xml b/spring-cloud/spring-cloud-openfeign/pom.xml new file mode 100644 index 0000000000..002a333749 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + com.baeldung.cloud + openfeign + 0.0.1-SNAPSHOT + openfeign + OpenFeign project for Spring Boot + + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + 2.0.1.RELEASE + Finchley.SR2 + + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + io.github.openfeign + feign-okhttp + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/ExampleApplication.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/ExampleApplication.java new file mode 100644 index 0000000000..c7f07f6667 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/ExampleApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.cloud.openfeign; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +@SpringBootApplication +@EnableFeignClients +public class ExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(ExampleApplication.class, args); + } + +} + diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/JSONPlaceHolderClient.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/JSONPlaceHolderClient.java new file mode 100644 index 0000000000..bdbe6efeeb --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/client/JSONPlaceHolderClient.java @@ -0,0 +1,25 @@ +package com.baeldung.cloud.openfeign.client; + +import com.baeldung.cloud.openfeign.config.ClientConfiguration; +import com.baeldung.cloud.openfeign.hystrix.JSONPlaceHolderFallback; +import com.baeldung.cloud.openfeign.model.Post; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.List; + +@FeignClient(value = "jplaceholder", + url = "https://jsonplaceholder.typicode.com/", + configuration = ClientConfiguration.class, + fallback = JSONPlaceHolderFallback.class) +public interface JSONPlaceHolderClient { + + @RequestMapping(method = RequestMethod.GET, value = "/posts") + List getPosts(); + + + @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json") + Post getPostById(@PathVariable("postId") Long postId); +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java new file mode 100644 index 0000000000..0b16134e92 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java @@ -0,0 +1,37 @@ +package com.baeldung.cloud.openfeign.config; + +import feign.Logger; +import feign.RequestInterceptor; +import feign.codec.ErrorDecoder; +import feign.okhttp.OkHttpClient; +import org.apache.http.entity.ContentType; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ClientConfiguration { + + @Bean + public Logger.Level feignLoggerLevel() { + return Logger.Level.FULL; + } + + @Bean + public ErrorDecoder errorDecoder() { + return new ErrorDecoder.Default(); + } + + @Bean + public OkHttpClient client() { + return new OkHttpClient(); + } + + @Bean + public RequestInterceptor requestInterceptor() { + return requestTemplate -> { + requestTemplate.header("user", "ajeje"); + requestTemplate.header("password", "brazof"); + requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType()); + }; + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/CustomErrorDecoder.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/CustomErrorDecoder.java new file mode 100644 index 0000000000..4d32cf083f --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/CustomErrorDecoder.java @@ -0,0 +1,21 @@ +package com.baeldung.cloud.openfeign.config; + +import com.baeldung.cloud.openfeign.exception.BadRequestException; +import com.baeldung.cloud.openfeign.exception.NotFoundException; +import feign.Response; +import feign.codec.ErrorDecoder; + +public class CustomErrorDecoder implements ErrorDecoder { + @Override + public Exception decode(String methodKey, Response response) { + + switch (response.status()){ + case 400: + return new BadRequestException(); + case 404: + return new NotFoundException(); + default: + return new Exception("Generic error"); + } + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/BadRequestException.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/BadRequestException.java new file mode 100644 index 0000000000..50200957ad --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/BadRequestException.java @@ -0,0 +1,21 @@ +package com.baeldung.cloud.openfeign.exception; + +public class BadRequestException extends Exception { + + public BadRequestException() { + } + + public BadRequestException(String message) { + super(message); + } + + public BadRequestException(Throwable cause) { + super(cause); + } + + @Override + public String toString() { + return "BadRequestException: "+getMessage(); + } + +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/NotFoundException.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/NotFoundException.java new file mode 100644 index 0000000000..28d0e95e9a --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/exception/NotFoundException.java @@ -0,0 +1,21 @@ +package com.baeldung.cloud.openfeign.exception; + +public class NotFoundException extends Exception { + + public NotFoundException() { + } + + public NotFoundException(String message) { + super(message); + } + + public NotFoundException(Throwable cause) { + super(cause); + } + + @Override + public String toString() { + return "NotFoundException: "+getMessage(); + } + +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/hystrix/JSONPlaceHolderFallback.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/hystrix/JSONPlaceHolderFallback.java new file mode 100644 index 0000000000..1aa3112320 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/hystrix/JSONPlaceHolderFallback.java @@ -0,0 +1,22 @@ +package com.baeldung.cloud.openfeign.hystrix; + +import com.baeldung.cloud.openfeign.client.JSONPlaceHolderClient; +import com.baeldung.cloud.openfeign.model.Post; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; + +@Component +public class JSONPlaceHolderFallback implements JSONPlaceHolderClient { + + @Override + public List getPosts() { + return Collections.emptyList(); + } + + @Override + public Post getPostById(Long postId) { + return null; + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Post.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Post.java new file mode 100644 index 0000000000..cab9629653 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/model/Post.java @@ -0,0 +1,41 @@ +package com.baeldung.cloud.openfeign.model; + +public class Post { + + private String userId; + private Long id; + private String title; + private String body; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/JSONPlaceHolderService.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/JSONPlaceHolderService.java new file mode 100644 index 0000000000..16e9b1dbde --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/JSONPlaceHolderService.java @@ -0,0 +1,12 @@ +package com.baeldung.cloud.openfeign.service; + +import com.baeldung.cloud.openfeign.model.Post; + +import java.util.List; + +public interface JSONPlaceHolderService { + + List getPosts(); + + Post getPostById(Long id); +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/impl/JSONPlaceHolderServiceImpl.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/impl/JSONPlaceHolderServiceImpl.java new file mode 100644 index 0000000000..30348db3c2 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/service/impl/JSONPlaceHolderServiceImpl.java @@ -0,0 +1,26 @@ +package com.baeldung.cloud.openfeign.service.impl; + +import com.baeldung.cloud.openfeign.client.JSONPlaceHolderClient; +import com.baeldung.cloud.openfeign.model.Post; +import com.baeldung.cloud.openfeign.service.JSONPlaceHolderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class JSONPlaceHolderServiceImpl implements JSONPlaceHolderService { + + @Autowired + private JSONPlaceHolderClient jsonPlaceHolderClient; + + @Override + public List getPosts() { + return jsonPlaceHolderClient.getPosts(); + } + + @Override + public Post getPostById(Long id) { + return jsonPlaceHolderClient.getPostById(id); + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties b/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties new file mode 100644 index 0000000000..41bbbde2c3 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.application.name= openfeign +logging.level.com.baeldung.cloud.openfeign.client: DEBUG +feign.hystrix.enabled=true diff --git a/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignUnitTest.java b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignUnitTest.java new file mode 100644 index 0000000000..72d2baa5d7 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.cloud.openfeign; + +import com.baeldung.cloud.openfeign.model.Post; +import com.baeldung.cloud.openfeign.service.JSONPlaceHolderService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class OpenfeignUnitTest { + + @Autowired + private JSONPlaceHolderService jsonPlaceHolderService; + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } + + @Test + public void whenGetPosts_thenListPostSizeGreaterThanZero() { + + List posts = jsonPlaceHolderService.getPosts(); + + assertFalse(posts.isEmpty()); + } + + @Test + public void whenGetPostWithId_thenPostExist() { + + Post post = jsonPlaceHolderService.getPostById(1L); + + assertNotNull(post); + } + +} From 7b3da0202ec8574f741cb12699f65b4c31bd46ce Mon Sep 17 00:00:00 2001 From: Chandra Prakash Date: Sat, 2 Mar 2019 07:52:09 -0500 Subject: [PATCH 193/496] BAEL-2504 Combinations Initial Combinations code. --- algorithms-miscellaneous-1/pom.xml | 5 +++ .../ApacheCommonsCombinationGenerator.java | 17 +++++++ .../CombinatoricsLibCombinationGenerator.java | 13 ++++++ .../GuavaCombinationsGenerator.java | 17 +++++++ .../IterativeCombinationGenerator.java | 45 +++++++++++++++++++ ...electionRecursiveCombinationGenerator.java | 39 ++++++++++++++++ .../SetRecursiveCombinationGenerator.java | 38 ++++++++++++++++ .../combination/CombinationUnitTest.java | 35 +++++++++++++++ 8 files changed, 209 insertions(+) create mode 100644 algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java create mode 100644 algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java create mode 100644 algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java create mode 100644 algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java create mode 100644 algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java create mode 100644 algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java create mode 100644 algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java diff --git a/algorithms-miscellaneous-1/pom.xml b/algorithms-miscellaneous-1/pom.xml index fe670963c0..0d528023d6 100644 --- a/algorithms-miscellaneous-1/pom.xml +++ b/algorithms-miscellaneous-1/pom.xml @@ -39,6 +39,11 @@ ${org.assertj.core.version} test + + com.github.dpaukov + combinatoricslib3 + 3.3.0 + diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java new file mode 100644 index 0000000000..4ec36927fa --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java @@ -0,0 +1,17 @@ +package com.baeldung.algorithms.combination; + +import java.util.Arrays; +import java.util.Iterator; + +import org.apache.commons.math3.util.CombinatoricsUtils; + +public class ApacheCommonsCombinationGenerator { + + public static void main(String[] args) { + Iterator iterator = CombinatoricsUtils.combinationsIterator(5, 3); + while (iterator.hasNext()) { + final int[] combination = iterator.next(); + System.out.println(Arrays.toString(combination)); + } + } +} \ No newline at end of file diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java new file mode 100644 index 0000000000..0afdeefb8b --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java @@ -0,0 +1,13 @@ +package com.baeldung.algorithms.combination; + +import org.paukov.combinatorics3.Generator; + +public class CombinatoricsLibCombinationGenerator { + + public static void main(String[] args) { + Generator.combination(0, 1, 2, 3, 4, 5) + .simple(3) + .stream() + .forEach(System.out::println); + } +} diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java new file mode 100644 index 0000000000..d2783881ba --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java @@ -0,0 +1,17 @@ +package com.baeldung.algorithms.combination; + +import java.util.Arrays; +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +public class GuavaCombinationsGenerator { + + public static void main(String[] args) { + + Set> combinations = Sets.combinations(ImmutableSet.of(0, 1, 2, 3, 4, 5), 3); + System.out.println(combinations.size()); + System.out.println(Arrays.toString(combinations.toArray())); + } +} diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java new file mode 100644 index 0000000000..a0c7222717 --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java @@ -0,0 +1,45 @@ +package com.baeldung.algorithms.combination; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class IterativeCombinationGenerator { + + private static final int N = 5; + private static final int R = 2; + + public List generate(int n, int r) { + List combinations = new ArrayList<>(); + int[] combination = new int[r]; + + for (int i = 0; i < r; i++) { + combination[i] = i; + } + + while (combination[r - 1] < n) { + combinations.add(combination.clone()); + + int t = r - 1; + while (t != 0 && combination[t] == n - r + t) { + t--; + } + combination[t]++; + for (int i = t + 1; i < r; i++) { + combination[i] = combination[i - 1] + 1; + } + } + + return combinations; + } + + public static void main(String[] args) { + IterativeCombinationGenerator generator = new IterativeCombinationGenerator(); + List combinations = generator.generate(N, R); + System.out.println(combinations.size()); + for (int[] combination : combinations) { + System.out.println(Arrays.toString(combination)); + } + } + +} diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java new file mode 100644 index 0000000000..400042b137 --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java @@ -0,0 +1,39 @@ +package com.baeldung.algorithms.combination; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SelectionRecursiveCombinationGenerator { + + private static final int N = 6; + private static final int R = 3; + + public List generate(int n, int r) { + List combinations = new ArrayList<>(); + helper(combinations, new int[r], 0, n - 1, 0); + return combinations; + } + + private void helper(List combinations, int data[], int start, int end, int index) { + if (index == data.length) { + int[] combination = data.clone(); + combinations.add(combination); + } else { + int max = Math.min(end, end + 1 - data.length + index); + for (int i = start; i <= max; i++) { + data[index] = i; + helper(combinations, data, i + 1, end, index + 1); + } + } + } + + public static void main(String[] args) { + SelectionRecursiveCombinationGenerator generator = new SelectionRecursiveCombinationGenerator(); + List combinations = generator.generate(N, R); + System.out.println(combinations.size()); + for (int[] combination : combinations) { + System.out.println(Arrays.toString(combination)); + } + } +} diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java new file mode 100644 index 0000000000..60c1c229b9 --- /dev/null +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java @@ -0,0 +1,38 @@ +package com.baeldung.algorithms.combination; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class SetRecursiveCombinationGenerator { + + private static final int N = 6; + private static final int R = 3; + + public List generate(int n, int r) { + List combinations = new ArrayList<>(); + helper(combinations, new int[r], 0, n - 1, 0, r); + return combinations; + } + + private void helper(List combinations, int data[], int start, int end, int index, int r) { + if (index == data.length) { + int[] combination = data.clone(); + combinations.add(combination); + + } else if (start <= end) { + data[index] = start; + helper(combinations, data, start + 1, end, index + 1, r); + helper(combinations, data, start + 1, end, index, r); + } + } + + public static void main(String[] args) { + SetRecursiveCombinationGenerator generator = new SetRecursiveCombinationGenerator(); + List combinations = generator.generate(N, R); + System.out.println(combinations.size()); + for (int[] combination : combinations) { + System.out.println(Arrays.toString(combination)); + } + } +} diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java new file mode 100644 index 0000000000..987b6ddae6 --- /dev/null +++ b/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.algorithms.combination; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; + +import org.junit.Test; + +public class CombinationUnitTest { + + private static final int N = 5; + private static final int R = 3; + private static final int nCr = 10; + + @Test + public void givenSetAndSelectionSize_whenCalculatedUsingSetRecursiveAlgorithm_thenExpectedCount() { + SetRecursiveCombinationGenerator generator = new SetRecursiveCombinationGenerator(); + List selection = generator.generate(N, R); + assertEquals(nCr, selection.size()); + } + + @Test + public void givenSetAndSelectionSize_whenCalculatedUsingSelectionRecursiveAlgorithm_thenExpectedCount() { + SelectionRecursiveCombinationGenerator generator = new SelectionRecursiveCombinationGenerator(); + List selection = generator.generate(N, R); + assertEquals(nCr, selection.size()); + } + + @Test + public void givenSetAndSelectionSize_whenCalculatedUsingIterativeAlgorithm_thenExpectedCount() { + IterativeCombinationGenerator generator = new IterativeCombinationGenerator(); + List selection = generator.generate(N, R); + assertEquals(nCr, selection.size()); + } +} From 7a3b11c4231e56b128f5b9472783bc7814eb0fc5 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sat, 2 Mar 2019 19:47:43 +0530 Subject: [PATCH 194/496] [BAEL-12774] - Upgraded spring boot versions --- parent-boot-1/pom.xml | 2 +- parent-boot-2/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parent-boot-1/pom.xml b/parent-boot-1/pom.xml index 53f91f975d..1054038623 100644 --- a/parent-boot-1/pom.xml +++ b/parent-boot-1/pom.xml @@ -55,7 +55,7 @@ 3.1.0 - 1.5.16.RELEASE + 1.5.19.RELEASE diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml index ef156e2e6a..4b81e27333 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -77,7 +77,7 @@ 3.1.0 - 1.0.11.RELEASE + 1.0.21.RELEASE 2.1.3.RELEASE From 3deeefe9107d1ff8936057b3dd35dc3a1a7d966b Mon Sep 17 00:00:00 2001 From: Krzysiek Date: Sat, 2 Mar 2019 19:58:07 +0100 Subject: [PATCH 195/496] BAEL-2755 - Introduction to the Null Object Pattern --- .../com/baeldung/nullobject/JmsRouter.java | 10 +++++++ .../java/com/baeldung/nullobject/Message.java | 24 +++++++++++++++ .../com/baeldung/nullobject/NullRouter.java | 10 +++++++ .../java/com/baeldung/nullobject/Router.java | 7 +++++ .../baeldung/nullobject/RouterFactory.java | 23 ++++++++++++++ .../baeldung/nullobject/RoutingHandler.java | 30 +++++++++++++++++++ .../com/baeldung/nullobject/SmsRouter.java | 10 +++++++ 7 files changed, 114 insertions(+) create mode 100644 patterns/design-patterns/src/main/java/com/baeldung/nullobject/JmsRouter.java create mode 100644 patterns/design-patterns/src/main/java/com/baeldung/nullobject/Message.java create mode 100644 patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java create mode 100644 patterns/design-patterns/src/main/java/com/baeldung/nullobject/Router.java create mode 100644 patterns/design-patterns/src/main/java/com/baeldung/nullobject/RouterFactory.java create mode 100644 patterns/design-patterns/src/main/java/com/baeldung/nullobject/RoutingHandler.java create mode 100644 patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/JmsRouter.java b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/JmsRouter.java new file mode 100644 index 0000000000..7d8215fead --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/JmsRouter.java @@ -0,0 +1,10 @@ +package com.baeldung.nullobject; + +public class JmsRouter implements Router { + + @Override + public void route(Message msg) { + System.out.println("Routing to a JMS queue. Msg: " + msg); + } + +} diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/Message.java b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/Message.java new file mode 100644 index 0000000000..9086b6d92d --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/Message.java @@ -0,0 +1,24 @@ +package com.baeldung.nullobject; + +public class Message { + + private String body; + + private String priority; + + public Message(String body, String priority) { + this.body = body; + this.priority = priority; + } + + public String getPriority() { + return priority; + } + + @Override + public String toString() { + return "{body='" + body + '\'' + + ", priority='" + priority + '\'' + + '}'; + } +} diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java new file mode 100644 index 0000000000..7da3856c93 --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java @@ -0,0 +1,10 @@ +package com.baeldung.nullobject; + +public class NullRouter implements Router { + + @Override + public void route(Message msg) { + // routing to /dev/null + } + +} diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/Router.java b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/Router.java new file mode 100644 index 0000000000..3e67de9558 --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/Router.java @@ -0,0 +1,7 @@ +package com.baeldung.nullobject; + +public interface Router { + + void route(Message msg); + +} diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/RouterFactory.java b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/RouterFactory.java new file mode 100644 index 0000000000..ba80834865 --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/RouterFactory.java @@ -0,0 +1,23 @@ +package com.baeldung.nullobject; + +public class RouterFactory { + + public static Router getRouterForMessage(Message msg) { + + if (msg.getPriority() == null) { + return new NullRouter(); + } + + switch (msg.getPriority()) { + case "high": + return new SmsRouter(); + + case "medium": + return new JmsRouter(); + + default: + return new NullRouter(); + } + + } +} diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/RoutingHandler.java b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/RoutingHandler.java new file mode 100644 index 0000000000..282b066085 --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/RoutingHandler.java @@ -0,0 +1,30 @@ +package com.baeldung.nullobject; + +import java.util.Arrays; +import java.util.List; + +public class RoutingHandler { + + public void handle(Iterable messages){ + for (Message msg : messages) { + Router router = RouterFactory.getRouterForMessage(msg); + router.route(msg); + } + } + + public static void main(String[] args) { + Message highPriorityMsg = new Message("Alert!", "high"); + Message mediumPriorityMsg = new Message("Warning!", "medium"); + Message lowPriorityMsg = new Message("Take a look!", "low"); + Message nullPriorityMsg = new Message("Take a look!", null); + + List messages = Arrays.asList(highPriorityMsg, + mediumPriorityMsg, + lowPriorityMsg, + nullPriorityMsg); + + RoutingHandler routingHandler = new RoutingHandler(); + routingHandler.handle(messages); + + } +} diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java new file mode 100644 index 0000000000..3d4a684f94 --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java @@ -0,0 +1,10 @@ +package com.baeldung.nullobject; + +public class SmsRouter implements Router { + + @Override + public void route(Message msg) { + System.out.println("Routing to a SMS gate. Msg: " + msg); + } + +} From 4826f19d00ed78c7efcafae0f6bfea79a3b9679d Mon Sep 17 00:00:00 2001 From: Jon Cook Date: Sat, 2 Mar 2019 22:50:04 +0100 Subject: [PATCH 196/496] BAEL-2512 - Add a new section in Mockito Spy article --- .../org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java index e2de23aa14..e39b8c0023 100644 --- a/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java +++ b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java @@ -17,6 +17,7 @@ public class MockitoMisusingUnitTest { public void givenNotASpy_whenDoReturn_thenThrowNotAMock() { try { List list = new ArrayList(); + Mockito.doReturn(100) .when(list) .size(); From 47eee45301d4bb7bfa4f8f5cb390a4ad7a3c1491 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Sun, 3 Mar 2019 07:24:02 +0800 Subject: [PATCH 197/496] BAEL-2581 Delegation Pattern in Kotlin --- .../kotlin/delegates/InterfaceDelegation.kt | 64 +++++++++++++++++++ .../delegates/InterfaceDelegationTest.kt | 28 ++++++++ 2 files changed, 92 insertions(+) create mode 100644 core-kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt create mode 100644 core-kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt diff --git a/core-kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt b/core-kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt new file mode 100644 index 0000000000..8e261aacf2 --- /dev/null +++ b/core-kotlin/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt @@ -0,0 +1,64 @@ +package com.baeldung.kotlin.delegates + +import java.util.concurrent.locks.ReentrantLock +import kotlin.concurrent.withLock + +interface Producer { + + fun produce(): String +} + +class ProducerImpl : Producer { + + override fun produce() = "ProducerImpl" +} + +class EnhancedProducer(private val delegate: Producer) : Producer by delegate { + + override fun produce() = "${delegate.produce()} and EnhancedProducer" +} + +interface MessageService { + + fun processMessage(message: String): String +} + +class MessageServiceImpl : MessageService { + override fun processMessage(message: String): String { + return "MessageServiceImpl: $message" + } +} + +interface UserService { + + fun processUser(userId: String): String +} + +class UserServiceImpl : UserService { + + override fun processUser(userId: String): String { + return "UserServiceImpl: $userId" + } +} + +class CompositeService : UserService by UserServiceImpl(), MessageService by MessageServiceImpl() + +interface Service { + + val seed: Int + + fun serve(action: (Int) -> Unit) +} + +class ServiceImpl : Service { + + override val seed = 1 + + override fun serve(action: (Int) -> Unit) { + action(seed) + } +} + +class ServiceDecorator : Service by ServiceImpl() { + override val seed = 2 +} \ No newline at end of file diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt new file mode 100644 index 0000000000..e65032acd4 --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt @@ -0,0 +1,28 @@ +package com.baeldung.kotlin.delegates + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + +class InterfaceDelegationTest { + + @Test + fun `when delegated implementation is used then it works as expected`() { + val producer = EnhancedProducer(ProducerImpl()) + assertThat(producer.produce()).isEqualTo("ProducerImpl and EnhancedProducer") + } + + @Test + fun `when composite delegation is used then it works as expected`() { + val service = CompositeService() + assertThat(service.processMessage("message")).isEqualTo("MessageServiceImpl: message") + assertThat(service.processUser("user")).isEqualTo("UserServiceImpl: user") + } + + @Test + fun `when decoration is used then delegate knows nothing about it`() { + val service = ServiceDecorator() + service.serve { + assertThat(it).isEqualTo(1) + } + } +} \ No newline at end of file From 01ab66f84fe328645b7b4bdcec7e6f95238aff72 Mon Sep 17 00:00:00 2001 From: Kacper Koza Date: Sun, 3 Mar 2019 00:11:21 +0100 Subject: [PATCH 198/496] Spy, mock, stub in Spock Framework --- testing-modules/groovy-spock/pom.xml | 4 +- .../main/java/mocks/CharacterCalculator.java | 15 ++ .../src/main/java/mocks/EventPublisher.java | 7 + .../mocks/ExternalItemProviderException.java | 5 + .../src/main/java/mocks/Item.java | 36 +++++ .../src/main/java/mocks/ItemProvider.java | 9 ++ .../src/main/java/mocks/ItemService.java | 37 +++++ .../java/mocks/LoggingEventPublisher.java | 10 ++ .../test/groovy/mocks/ExampleSpockTest.groovy | 26 ++++ .../test/groovy/mocks/ItemServiceTest.groovy | 131 ++++++++++++++++++ 10 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 testing-modules/groovy-spock/src/main/java/mocks/CharacterCalculator.java create mode 100644 testing-modules/groovy-spock/src/main/java/mocks/EventPublisher.java create mode 100644 testing-modules/groovy-spock/src/main/java/mocks/ExternalItemProviderException.java create mode 100644 testing-modules/groovy-spock/src/main/java/mocks/Item.java create mode 100644 testing-modules/groovy-spock/src/main/java/mocks/ItemProvider.java create mode 100644 testing-modules/groovy-spock/src/main/java/mocks/ItemService.java create mode 100644 testing-modules/groovy-spock/src/main/java/mocks/LoggingEventPublisher.java create mode 100644 testing-modules/groovy-spock/src/test/groovy/mocks/ExampleSpockTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceTest.groovy diff --git a/testing-modules/groovy-spock/pom.xml b/testing-modules/groovy-spock/pom.xml index 3dd01c29ab..77b6fbeb28 100644 --- a/testing-modules/groovy-spock/pom.xml +++ b/testing-modules/groovy-spock/pom.xml @@ -48,9 +48,9 @@ - 1.0-groovy-2.4 + 1.3-RC1-groovy-2.4 2.4.7 1.5 - \ No newline at end of file + diff --git a/testing-modules/groovy-spock/src/main/java/mocks/CharacterCalculator.java b/testing-modules/groovy-spock/src/main/java/mocks/CharacterCalculator.java new file mode 100644 index 0000000000..92a0cabdcb --- /dev/null +++ b/testing-modules/groovy-spock/src/main/java/mocks/CharacterCalculator.java @@ -0,0 +1,15 @@ +package mocks; + +public class CharacterCalculator { + + public int countCharacterInString(String value, char characterToCount) { + int result = 0; + for (int i = 0; i < value.length(); i++) { + if (value.charAt(i) == characterToCount) { + result++; + } + } + return result; + } + +} diff --git a/testing-modules/groovy-spock/src/main/java/mocks/EventPublisher.java b/testing-modules/groovy-spock/src/main/java/mocks/EventPublisher.java new file mode 100644 index 0000000000..290966db9f --- /dev/null +++ b/testing-modules/groovy-spock/src/main/java/mocks/EventPublisher.java @@ -0,0 +1,7 @@ +package mocks; + +public interface EventPublisher { + + void publish(String addedOfferId); + +} diff --git a/testing-modules/groovy-spock/src/main/java/mocks/ExternalItemProviderException.java b/testing-modules/groovy-spock/src/main/java/mocks/ExternalItemProviderException.java new file mode 100644 index 0000000000..e2ac43b7f4 --- /dev/null +++ b/testing-modules/groovy-spock/src/main/java/mocks/ExternalItemProviderException.java @@ -0,0 +1,5 @@ +package mocks; + +public class ExternalItemProviderException extends RuntimeException { + +} diff --git a/testing-modules/groovy-spock/src/main/java/mocks/Item.java b/testing-modules/groovy-spock/src/main/java/mocks/Item.java new file mode 100644 index 0000000000..e1608cfd23 --- /dev/null +++ b/testing-modules/groovy-spock/src/main/java/mocks/Item.java @@ -0,0 +1,36 @@ +package mocks; + +import java.util.Objects; + +public class Item { + private final String id; + private final String name; + + public Item(String id, String name) { + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Item item = (Item) o; + return Objects.equals(id, item.id) && + Objects.equals(name, item.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + +} diff --git a/testing-modules/groovy-spock/src/main/java/mocks/ItemProvider.java b/testing-modules/groovy-spock/src/main/java/mocks/ItemProvider.java new file mode 100644 index 0000000000..a794c51f49 --- /dev/null +++ b/testing-modules/groovy-spock/src/main/java/mocks/ItemProvider.java @@ -0,0 +1,9 @@ +package mocks; + +import java.util.List; + +public interface ItemProvider { + + List getItems(List itemIds); + +} diff --git a/testing-modules/groovy-spock/src/main/java/mocks/ItemService.java b/testing-modules/groovy-spock/src/main/java/mocks/ItemService.java new file mode 100644 index 0000000000..3327a8b27c --- /dev/null +++ b/testing-modules/groovy-spock/src/main/java/mocks/ItemService.java @@ -0,0 +1,37 @@ +package mocks; + +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +public class ItemService { + private final ItemProvider itemProvider; + private final EventPublisher eventPublisher; + + + public ItemService(ItemProvider itemProvider, EventPublisher eventPublisher) { + this.itemProvider = itemProvider; + this.eventPublisher = eventPublisher; + } + + List getAllItemsSortedByName(List itemIds) { + List items; + try{ + items = itemProvider.getItems(itemIds); + } catch (RuntimeException ex) { + throw new ExternalItemProviderException(); + } + return items.stream() + .sorted(Comparator.comparing(Item::getName)) + .collect(Collectors.toList()); + } + + void saveItems(List itemIds) { + List notEmptyOfferIds = itemIds.stream() + .filter(itemId -> !itemId.isEmpty()) + .collect(Collectors.toList()); + // save in database + notEmptyOfferIds.forEach(eventPublisher::publish); + } + +} diff --git a/testing-modules/groovy-spock/src/main/java/mocks/LoggingEventPublisher.java b/testing-modules/groovy-spock/src/main/java/mocks/LoggingEventPublisher.java new file mode 100644 index 0000000000..c51fe1ff77 --- /dev/null +++ b/testing-modules/groovy-spock/src/main/java/mocks/LoggingEventPublisher.java @@ -0,0 +1,10 @@ +package mocks; + +public class LoggingEventPublisher implements EventPublisher { + + @Override + public void publish(String addedOfferId) { + System.out.println("I've published: " + addedOfferId); + } + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/mocks/ExampleSpockTest.groovy b/testing-modules/groovy-spock/src/test/groovy/mocks/ExampleSpockTest.groovy new file mode 100644 index 0000000000..3d424b0796 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/mocks/ExampleSpockTest.groovy @@ -0,0 +1,26 @@ +package mocks + +import spock.lang.Specification + +class ExampleSpockTest extends Specification { + + CharacterCalculator characterCalculator + + def setup() { + characterCalculator = new CharacterCalculator() + } + + def 'should calculate character occurrences in given string'() { + given: + char characterToCount = 'o' + String value = 'Hello world!' + + when: + int result = characterCalculator.countCharacterInString(value, characterToCount) + + then: + result == 2 + } + + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceTest.groovy b/testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceTest.groovy new file mode 100644 index 0000000000..2c7c4402e9 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceTest.groovy @@ -0,0 +1,131 @@ +package mocks + +import spock.lang.Specification + +class ItemServiceTest extends Specification { + + ItemProvider itemProvider + ItemService itemService + EventPublisher eventPublisher + + def setup() { + itemProvider = Stub(ItemProvider) + eventPublisher = Mock(EventPublisher) + itemService = new ItemService(itemProvider, eventPublisher) + } + + def 'should return items sorted by name'() { + given: + def ids = ['offer-id', 'offer-id-2'] + itemProvider.getItems(ids) >> [new Item('offer-id-2', 'Zname'), new Item('offer-id', 'Aname')] + + when: + List items = itemService.getAllItemsSortedByName(ids) + + then: + items.collect { it.name } == ['Aname', 'Zname'] + } + + def 'arguments constraints'() { + itemProvider.getItems(['offer-id']) + itemProvider.getItems(_) >> [] + itemProvider.getItems(*_) >> [] + itemProvider.getItems(!null) >> [] + itemProvider.getItems({ it.size > 0 }) >> [] + } + + def 'should return different items on subsequent call'() { + given: + itemProvider.getItems(_) >>> [ + [], + [new Item('1', 'name')], + [new Item('2', 'name')] + ] + + when: 'method is called for the first time' + List items = itemService.getAllItemsSortedByName(['not-important']) + + then: 'empty list is returned' + items == [] + + when: 'method is called for the second time' + items = itemService.getAllItemsSortedByName(['not-important']) + + then: 'item with id=1 is returned' + items == [new Item('1', 'name')] + + when: 'method is called for the thirdtime' + items = itemService.getAllItemsSortedByName(['not-important']) + + then: 'item with id=2 is returned' + items == [new Item('2', 'name')] + } + + def 'should throw ExternalItemProviderException when ItemProvider fails'() { + given: + itemProvider.getItems(_) >> { new RuntimeException()} + + when: + itemService.getAllItemsSortedByName([]) + + then: + thrown(ExternalItemProviderException) + } + + def 'chaining response'() { + itemProvider.getItems(_) >>> { new RuntimeException() } >> new SocketTimeoutException() >> [new Item('id', 'name')] + } + + def 'should return different items for different ids lists'() { + given: + def firstIds = ['first'] + def secondIds = ['second'] + itemProvider.getItems(firstIds) >> [new Item('first', 'Zname')] + itemProvider.getItems(secondIds) >> [new Item('second', 'Aname')] + + when: + def firstItems = itemService.getAllItemsSortedByName(firstIds) + def secondItems = itemService.getAllItemsSortedByName(secondIds) + + then: + firstItems.first().name == 'Zname' + secondItems.first().name == 'Aname' + } + + def 'should publish events about new non-empty saved offers'() { + given: + def offerIds = ['', 'a', 'b'] + + when: + itemService.saveItems(offerIds) + + then: + 2 * eventPublisher.publish({ it != null && !it.isEmpty()}) + } + + def 'should return items'() { + given: + itemProvider = Mock(ItemProvider) + itemProvider.getItems(['item-id']) >> [new Item('item-id', 'name')] + itemService = new ItemService(itemProvider, eventPublisher) + + when: + def items = itemService.getAllItemsSortedByName(['item-id']) + + then: + items == [new Item('item-id', 'name')] + } + + def 'should spy on EventPublisher method call'() { + given: + LoggingEventPublisher eventPublisher = Spy(LoggingEventPublisher) + itemService = new ItemService(itemProvider, eventPublisher) + + when: + itemService.saveItems(['item-id']) + + then: + 1 * eventPublisher.publish('item-id') + } + +} From 6ecbe4b20adbe69bfb762b8a3bb4b0db280c8a10 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 3 Mar 2019 08:27:57 +0200 Subject: [PATCH 199/496] Update MockitoMisusingUnitTest.java --- .../org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java index e2de23aa14..2935f7ea8a 100644 --- a/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java +++ b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java @@ -26,5 +26,4 @@ public class MockitoMisusingUnitTest { assertThat(e.getMessage(), containsString("Argument passed to when() is not a mock!")); } } - } From 24a3fa2ae700cc0c6a1a26b77fa828648c31f37c Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 3 Mar 2019 09:16:10 +0200 Subject: [PATCH 200/496] Update and rename ItemServiceTest.groovy to ItemServiceUnitTest.groovy --- .../{ItemServiceTest.groovy => ItemServiceUnitTest.groovy} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename testing-modules/groovy-spock/src/test/groovy/mocks/{ItemServiceTest.groovy => ItemServiceUnitTest.groovy} (98%) diff --git a/testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceTest.groovy b/testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceUnitTest.groovy similarity index 98% rename from testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceTest.groovy rename to testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceUnitTest.groovy index 2c7c4402e9..2ccb72f726 100644 --- a/testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceTest.groovy +++ b/testing-modules/groovy-spock/src/test/groovy/mocks/ItemServiceUnitTest.groovy @@ -2,7 +2,7 @@ package mocks import spock.lang.Specification -class ItemServiceTest extends Specification { +class ItemServiceUnitTest extends Specification { ItemProvider itemProvider ItemService itemService From 9611f5a5cf3b8b072b007dc701c3ce31be6efb74 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 3 Mar 2019 09:16:36 +0200 Subject: [PATCH 201/496] Delete ExampleSpockTest.groovy --- .../test/groovy/mocks/ExampleSpockTest.groovy | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 testing-modules/groovy-spock/src/test/groovy/mocks/ExampleSpockTest.groovy diff --git a/testing-modules/groovy-spock/src/test/groovy/mocks/ExampleSpockTest.groovy b/testing-modules/groovy-spock/src/test/groovy/mocks/ExampleSpockTest.groovy deleted file mode 100644 index 3d424b0796..0000000000 --- a/testing-modules/groovy-spock/src/test/groovy/mocks/ExampleSpockTest.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package mocks - -import spock.lang.Specification - -class ExampleSpockTest extends Specification { - - CharacterCalculator characterCalculator - - def setup() { - characterCalculator = new CharacterCalculator() - } - - def 'should calculate character occurrences in given string'() { - given: - char characterToCount = 'o' - String value = 'Hello world!' - - when: - int result = characterCalculator.countCharacterInString(value, characterToCount) - - then: - result == 2 - } - - -} From 84c8c70dac1d1786471197e269cf1fe59ad5931a Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 3 Mar 2019 09:16:43 +0200 Subject: [PATCH 202/496] Delete CharacterCalculator.java --- .../src/main/java/mocks/CharacterCalculator.java | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 testing-modules/groovy-spock/src/main/java/mocks/CharacterCalculator.java diff --git a/testing-modules/groovy-spock/src/main/java/mocks/CharacterCalculator.java b/testing-modules/groovy-spock/src/main/java/mocks/CharacterCalculator.java deleted file mode 100644 index 92a0cabdcb..0000000000 --- a/testing-modules/groovy-spock/src/main/java/mocks/CharacterCalculator.java +++ /dev/null @@ -1,15 +0,0 @@ -package mocks; - -public class CharacterCalculator { - - public int countCharacterInString(String value, char characterToCount) { - int result = 0; - for (int i = 0; i < value.length(); i++) { - if (value.charAt(i) == characterToCount) { - result++; - } - } - return result; - } - -} From 86b51e41571082a4cbd732bb386aac9c4a5ed881 Mon Sep 17 00:00:00 2001 From: Jon Cook Date: Sun, 3 Mar 2019 08:45:45 +0100 Subject: [PATCH 203/496] BAEL-2512 - Add a new section in Mockito Spy article --- .../misusing/MockitoMisusingUnitTest.java | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java diff --git a/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java deleted file mode 100644 index e39b8c0023..0000000000 --- a/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.baeldung.mockito.misusing; - -import static org.hamcrest.core.StringContains.containsString; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; -import org.mockito.Mockito; -import org.mockito.exceptions.misusing.NotAMockException; - -public class MockitoMisusingUnitTest { - - @Test - public void givenNotASpy_whenDoReturn_thenThrowNotAMock() { - try { - List list = new ArrayList(); - - Mockito.doReturn(100) - .when(list) - .size(); - - fail("Should have thrown a NotAMockException because 'list' is not a mock!"); - } catch (NotAMockException e) { - assertThat(e.getMessage(), containsString("Argument passed to when() is not a mock!")); - } - } - -} From 23e3e6c7088077b030c6a6cdad40c9dc39699b31 Mon Sep 17 00:00:00 2001 From: Krzysiek Date: Sun, 3 Mar 2019 10:33:31 +0100 Subject: [PATCH 204/496] BAEL-2755 - minor improvements --- .../src/main/java/com/baeldung/nullobject/NullRouter.java | 2 +- .../src/main/java/com/baeldung/nullobject/SmsRouter.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java index 7da3856c93..a0065a321d 100644 --- a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java +++ b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java @@ -4,7 +4,7 @@ public class NullRouter implements Router { @Override public void route(Message msg) { - // routing to /dev/null + // do nothing } } diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java index 3d4a684f94..3e8e2f15f3 100644 --- a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java +++ b/patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java @@ -4,7 +4,7 @@ public class SmsRouter implements Router { @Override public void route(Message msg) { - System.out.println("Routing to a SMS gate. Msg: " + msg); + System.out.println("Routing to a SMS gateway. Msg: " + msg); } } From 9838dca33acaf295e5d5c4f511deb6f8d78bb5b6 Mon Sep 17 00:00:00 2001 From: Jon Cook Date: Sun, 3 Mar 2019 15:18:14 +0100 Subject: [PATCH 205/496] BAEL-2512 - Add a new section in Mockito Spy article --- .../misusing/MockitoMisusingUnitTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java diff --git a/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java new file mode 100644 index 0000000000..306f53297a --- /dev/null +++ b/testing-modules/mockito/src/test/java/org/baeldung/mockito/misusing/MockitoMisusingUnitTest.java @@ -0,0 +1,38 @@ +package org.baeldung.mockito.misusing; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.exceptions.misusing.NotAMockException; +import org.mockito.internal.progress.ThreadSafeMockingProgress; + +public class MockitoMisusingUnitTest { + + @After + public void tearDown() { + ThreadSafeMockingProgress.mockingProgress().reset(); + } + + @Test + public void givenNotASpy_whenDoReturn_thenThrowNotAMock() { + try { + List list = new ArrayList(); + + Mockito.doReturn(100, Mockito.withSettings().lenient()) + .when(list) + .size(); + + fail("Should have thrown a NotAMockException because 'list' is not a mock!"); + } catch (NotAMockException e) { + assertThat(e.getMessage(), containsString("Argument passed to when() is not a mock!")); + } + } + +} From 09e7e619017df5b8024adb50505d138d51636b38 Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Sun, 3 Mar 2019 09:19:12 -0600 Subject: [PATCH 206/496] BAEL-2490 BAEL-2471 BAEL-2738 BAEL-2583 update README.md (#6457) * BAEL-2246: add link back to article * BAEL-2174: rename core-java-net module to core-java-networking * BAEL-2174: add link back to article * BAEL-2363 BAEL-2337 BAEL-1996 BAEL-2277 add links back to articles * BAEL-2367: add link back to article * BAEL-2335: add link back to article * BAEL-2413: add link back to article * Update README.MD * BAEL-2577: add link back to article * BAEL-2490: add link back to article * BAEL-2471: add link back to article * BAEL-2583: add link back to article * BAEL-2738: add link back to article --- gson/README.md | 1 + java-collections-maps/README.md | 1 + testing-modules/junit-5/README.md | 1 + testing-modules/spring-testing/README.md | 1 + 4 files changed, 4 insertions(+) diff --git a/gson/README.md b/gson/README.md index 4edd7158d4..02b06eac20 100644 --- a/gson/README.md +++ b/gson/README.md @@ -10,3 +10,4 @@ - [Save Data to a JSON File with Gson](https://www.baeldung.com/gson-save-file) - [Convert JSON to a Map Using Gson](https://www.baeldung.com/gson-json-to-map) - [Working with Primitive Values in Gson](https://www.baeldung.com/java-gson-primitives) +- [Convert String to JsonObject with Gson](https://www.baeldung.com/gson-string-to-jsonobject) diff --git a/java-collections-maps/README.md b/java-collections-maps/README.md index 5d65e961de..2eeb2c8843 100644 --- a/java-collections-maps/README.md +++ b/java-collections-maps/README.md @@ -20,3 +20,4 @@ - [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps) - [Immutable Map Implementations in Java](https://www.baeldung.com/java-immutable-maps) - [Map to String Conversion in Java](https://www.baeldung.com/java-map-to-string-conversion) +- [Guide to Apache Commons MultiValuedMap](https://www.baeldung.com/apache-commons-multi-valued-map) diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md index 4ed01e7fa9..d46f8bf1cf 100644 --- a/testing-modules/junit-5/README.md +++ b/testing-modules/junit-5/README.md @@ -17,3 +17,4 @@ - [Testing an Abstract Class With JUnit](https://www.baeldung.com/junit-test-abstract-class) - [A Quick JUnit vs TestNG Comparison](http://www.baeldung.com/junit-vs-testng) - [Guide to JUnit 5 Parameterized Tests](https://www.baeldung.com/parameterized-tests-junit-5) +- [JUnit 5 Conditional Test Execution with Annotations](https://www.baeldung.com/junit-5-conditional-test-execution) diff --git a/testing-modules/spring-testing/README.md b/testing-modules/spring-testing/README.md index 02ab7b24bd..8eb282643a 100644 --- a/testing-modules/spring-testing/README.md +++ b/testing-modules/spring-testing/README.md @@ -3,3 +3,4 @@ - [Mockito.mock() vs @Mock vs @MockBean](http://www.baeldung.com/java-spring-mockito-mock-mockbean) - [A Quick Guide to @TestPropertySource](https://www.baeldung.com/spring-test-property-source) - [Guide to ReflectionTestUtils for Unit Testing](https://www.baeldung.com/spring-reflection-test-utils) +- [How to Test the @Scheduled Annotation](https://www.baeldung.com/spring-testing-scheduled-annotation) From 1475c3e32d32b318d2f59fa5e49392bf6343d722 Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 3 Mar 2019 17:59:20 +0200 Subject: [PATCH 207/496] fix sleuth ex --- .../spring/session/SleuthService.java | 2 +- spring-sleuth/src/main/resources/logback.xml | 27 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/spring-sleuth/src/main/java/com/baeldung/spring/session/SleuthService.java b/spring-sleuth/src/main/java/com/baeldung/spring/session/SleuthService.java index 511a6078f5..df5313580a 100644 --- a/spring-sleuth/src/main/java/com/baeldung/spring/session/SleuthService.java +++ b/spring-sleuth/src/main/java/com/baeldung/spring/session/SleuthService.java @@ -28,7 +28,7 @@ public class SleuthService { public void doSomeWorkNewSpan() throws InterruptedException { logger.info("I'm in the original span"); - Span newSpan = tracer.newTrace().name("newSpan").start(); + Span newSpan = tracer.nextSpan().name("newSpan").start(); try (SpanInScope ws = tracer.withSpanInScope(newSpan.start())) { Thread.sleep(1000L); logger.info("I'm in the new span doing some cool work that needs its own span"); diff --git a/spring-sleuth/src/main/resources/logback.xml b/spring-sleuth/src/main/resources/logback.xml index 7d900d8ea8..044adaaf1d 100644 --- a/spring-sleuth/src/main/resources/logback.xml +++ b/spring-sleuth/src/main/resources/logback.xml @@ -1,13 +1,20 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file From 19cf211ddfa2a0cca1a0eaa3b7230ab9302f9e8e Mon Sep 17 00:00:00 2001 From: eric-martin Date: Sun, 3 Mar 2019 10:36:36 -0600 Subject: [PATCH 208/496] BAEL-2496: Updated ArraySortBenchmark --- .../performance/ArraySortBenchmark.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java index a1d40657d3..b93f8e9cc2 100644 --- a/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java +++ b/core-java-collections/src/main/java/com/baeldung/performance/ArraySortBenchmark.java @@ -1,17 +1,21 @@ package com.baeldung.performance; -import org.openjdk.jmh.annotations.*; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.TimeUnit; - -@BenchmarkMode(Mode.SingleShotTime) +@BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) @Measurement(batchSize = 100000, iterations = 10) @Warmup(batchSize = 100000, iterations = 10) @@ -19,8 +23,8 @@ public class ArraySortBenchmark { @State(Scope.Thread) public static class Initialize { - Integer[] numbers = {5, 22, 10, 0}; - int[] primitives = {5, 22, 10, 0}; + Integer[] numbers = { -769214442, -1283881723, 1504158300, -1260321086, -1800976432, 1278262737, 1863224321, 1895424914, 2062768552, -1051922993, 751605209, -1500919212, 2094856518, -1014488489, -931226326, -1677121986, -2080561705, 562424208, -1233745158, 41308167 }; + int[] primitives = { -769214442, -1283881723, 1504158300, -1260321086, -1800976432, 1278262737, 1863224321, 1895424914, 2062768552, -1051922993, 751605209, -1500919212, 2094856518, -1014488489, -931226326, -1677121986, -2080561705, 562424208, -1233745158, 41308167 }; } @Benchmark From 2b8ebe7de23c8e632121c3380423e45750da2dde Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 3 Mar 2019 01:33:22 +0530 Subject: [PATCH 209/496] [BAEL-12185] - Updated JACKSON ANNOTATIONS article --- .../serialization/jsonrootname/Author.java | 2 +- .../jackson/annotation/AliasBean.java | 31 ++++++++++++++ .../test/JacksonAnnotationUnitTest.java | 41 +++++++++++++++++++ pom.xml | 2 +- 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 jackson/src/test/java/com/baeldung/jackson/annotation/AliasBean.java diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrootname/Author.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrootname/Author.java index c6ebfd10fb..b6dd75da54 100644 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrootname/Author.java +++ b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrootname/Author.java @@ -13,7 +13,7 @@ import java.util.List; * @author Alex Theedom www.readlearncode.com * @version 1.0 */ -@JsonRootName("writer") +@JsonRootName(value = "writer", namespace = "book") public class Author extends Person { List items = new ArrayList<>(); diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/AliasBean.java b/jackson/src/test/java/com/baeldung/jackson/annotation/AliasBean.java new file mode 100644 index 0000000000..1842b2b6f5 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/annotation/AliasBean.java @@ -0,0 +1,31 @@ +package com.baeldung.jackson.annotation; + +import com.fasterxml.jackson.annotation.JsonAlias; + +public class AliasBean { + + @JsonAlias({ "fName", "f_name" }) + private String firstName; + + private String lastName; + + public AliasBean() { + + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java index 935777bad1..c8c4c592f0 100644 --- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java @@ -14,6 +14,7 @@ import java.util.TimeZone; import org.junit.Test; +import com.baeldung.jackson.annotation.AliasBean; import com.baeldung.jackson.annotation.BeanWithCreator; import com.baeldung.jackson.annotation.BeanWithCustomAnnotation; import com.baeldung.jackson.annotation.BeanWithFilter; @@ -38,6 +39,7 @@ import com.baeldung.jackson.dtos.withEnum.DistanceEnumWithValue; import com.baeldung.jackson.exception.UserWithRoot; import com.baeldung.jackson.jsonview.Item; import com.baeldung.jackson.jsonview.Views; +import com.baeldung.jackson.serialization.jsonrootname.Author; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.InjectableValues; import com.fasterxml.jackson.databind.MapperFeature; @@ -46,6 +48,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; public class JacksonAnnotationUnitTest { @@ -372,5 +375,43 @@ public class JacksonAnnotationUnitTest { assertThat(result, containsString("1")); assertThat(result, containsString("name")); } + + @Test + public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException { + + // arrange + String json = "{\"fName\": \"Alex\", \"lastName\": \"Theedom\"}"; + + // act + AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json); + + // assert + assertThat(aliasBean.getFirstName(), is("Alex")); + } + + @Test + public void whenSerializingUsingXMLRootNameWithNameSpace_thenCorrect() throws JsonProcessingException { + + // arrange + Author author = new Author("Alex", "Theedom"); + + // act + ObjectMapper mapper = new XmlMapper(); + mapper = mapper.enable(SerializationFeature.WRAP_ROOT_VALUE).enable(SerializationFeature.INDENT_OUTPUT); + String result = mapper.writeValueAsString(author); + + // assert + assertThat(result, containsString("")); + + /* + + 3006b44a-cf62-4cfe-b3d8-30dc6c46ea96 + Alex + Theedom + + + */ + + } } diff --git a/pom.xml b/pom.xml index 0a401299ba..81f55e3cbf 100644 --- a/pom.xml +++ b/pom.xml @@ -1630,7 +1630,7 @@ 2.3.1 1.9.13 1.2 - 2.9.7 + 2.9.8 1.3 1.2.0 5.2.0 From b796bb014639a30245f336c1761d5e88438a5651 Mon Sep 17 00:00:00 2001 From: Chandra Prakash Date: Sun, 3 Mar 2019 18:14:03 -0500 Subject: [PATCH 210/496] guava library updated to 27.0.1 upgraded guava library to 27.0.1 added javadoc --- algorithms-miscellaneous-1/pom.xml | 2 +- .../ApacheCommonsCombinationGenerator.java | 16 +++++++++-- .../IterativeCombinationGenerator.java | 11 ++++++-- ...electionRecursiveCombinationGenerator.java | 16 ++++++++++- .../SetRecursiveCombinationGenerator.java | 28 +++++++++++++------ 5 files changed, 59 insertions(+), 14 deletions(-) diff --git a/algorithms-miscellaneous-1/pom.xml b/algorithms-miscellaneous-1/pom.xml index 0d528023d6..30130208f8 100644 --- a/algorithms-miscellaneous-1/pom.xml +++ b/algorithms-miscellaneous-1/pom.xml @@ -82,7 +82,7 @@ 3.6.1 3.9.0 1.11 - 25.1-jre + 27.0.1-jre \ No newline at end of file diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java index 4ec36927fa..40142ce940 100644 --- a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java @@ -7,11 +7,23 @@ import org.apache.commons.math3.util.CombinatoricsUtils; public class ApacheCommonsCombinationGenerator { - public static void main(String[] args) { - Iterator iterator = CombinatoricsUtils.combinationsIterator(5, 3); + private static final int N = 6; + private static final int R = 3; + + /** + * Print all combinations of r elements from a set + * @param n - number of elements in set + * @param r - number of elements in selection + */ + public static void generate(int n, int r) { + Iterator iterator = CombinatoricsUtils.combinationsIterator(n, r); while (iterator.hasNext()) { final int[] combination = iterator.next(); System.out.println(Arrays.toString(combination)); } } + + public static void main(String[] args) { + generate(N, R); + } } \ No newline at end of file diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java index a0c7222717..676d2f41e3 100644 --- a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java @@ -5,14 +5,21 @@ import java.util.Arrays; import java.util.List; public class IterativeCombinationGenerator { - + private static final int N = 5; private static final int R = 2; + /** + * Generate all combinations of r elements from a set + * @param n the number of elements in input set + * @param r the number of elements in a combination + * @return the list containing all combinations + */ public List generate(int n, int r) { List combinations = new ArrayList<>(); int[] combination = new int[r]; + // initialize with lowest lexicographic combination for (int i = 0; i < r; i++) { combination[i] = i; } @@ -20,6 +27,7 @@ public class IterativeCombinationGenerator { while (combination[r - 1] < n) { combinations.add(combination.clone()); + // generate next combination in lexicographic order int t = r - 1; while (t != 0 && combination[t] == n - r + t) { t--; @@ -41,5 +49,4 @@ public class IterativeCombinationGenerator { System.out.println(Arrays.toString(combination)); } } - } diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java index 400042b137..52305b8c2f 100644 --- a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java @@ -9,12 +9,26 @@ public class SelectionRecursiveCombinationGenerator { private static final int N = 6; private static final int R = 3; + /** + * Generate all combinations of r elements from a set + * @param n - number of elements in input set + * @param r - number of elements to be chosen + * @return the list containing all combinations + */ public List generate(int n, int r) { List combinations = new ArrayList<>(); helper(combinations, new int[r], 0, n - 1, 0); return combinations; } + /** + * Choose elements from set by recursing over elements selected + * @param combinations - List to store generated combinations + * @param data - current combination + * @param start - starting element of remaining set + * @param end - last element of remaining set + * @param index - number of elements chosen so far. + */ private void helper(List combinations, int data[], int start, int end, int index) { if (index == data.length) { int[] combination = data.clone(); @@ -31,9 +45,9 @@ public class SelectionRecursiveCombinationGenerator { public static void main(String[] args) { SelectionRecursiveCombinationGenerator generator = new SelectionRecursiveCombinationGenerator(); List combinations = generator.generate(N, R); - System.out.println(combinations.size()); for (int[] combination : combinations) { System.out.println(Arrays.toString(combination)); } + System.out.printf("generated %d combinations of %d items from %d ", combinations.size(), R, N); } } diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java index 60c1c229b9..a73447b31d 100644 --- a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java +++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java @@ -6,33 +6,45 @@ import java.util.List; public class SetRecursiveCombinationGenerator { - private static final int N = 6; - private static final int R = 3; + private static final int N = 5; + private static final int R = 2; + /** + * Generate all combinations of r elements from a set + * @param n - number of elements in set + * @param r - number of elements in selection + * @return the list containing all combinations + */ public List generate(int n, int r) { List combinations = new ArrayList<>(); - helper(combinations, new int[r], 0, n - 1, 0, r); + helper(combinations, new int[r], 0, n-1, 0); return combinations; } - private void helper(List combinations, int data[], int start, int end, int index, int r) { + /** + * @param combinations - List to contain the generated combinations + * @param data - List of elements in the selection + * @param start - index of the starting element in the remaining set + * @param end - index of the last element in the set + * @param index - number of elements selected so far + */ + private void helper(List combinations, int data[], int start, int end, int index) { if (index == data.length) { int[] combination = data.clone(); combinations.add(combination); - } else if (start <= end) { data[index] = start; - helper(combinations, data, start + 1, end, index + 1, r); - helper(combinations, data, start + 1, end, index, r); + helper(combinations, data, start + 1, end, index + 1); + helper(combinations, data, start + 1, end, index); } } public static void main(String[] args) { SetRecursiveCombinationGenerator generator = new SetRecursiveCombinationGenerator(); List combinations = generator.generate(N, R); - System.out.println(combinations.size()); for (int[] combination : combinations) { System.out.println(Arrays.toString(combination)); } + System.out.printf("generated %d combinations of %d items from %d ", combinations.size(), R, N); } } From 00c115229bed0b072afd1e4170cb3c6bd4f7cda0 Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Mon, 4 Mar 2019 08:06:11 +0530 Subject: [PATCH 211/496] Bael 2560 spring jms error handler (#6447) * Spring jms error handler * BAEL-2560 Reverting a change --- .../spring/jms/SampleJmsErrorHandler.java | 17 +++++ .../spring/jms/SampleJmsMessageSender.java | 4 + .../baeldung/spring/jms/SampleListener.java | 4 + .../src/main/resources/applicationContext.xml | 75 +++++++++---------- ...faultTextMessageSenderIntegrationTest.java | 7 ++ 5 files changed, 68 insertions(+), 39 deletions(-) create mode 100644 spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsErrorHandler.java diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsErrorHandler.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsErrorHandler.java new file mode 100644 index 0000000000..220b2744f3 --- /dev/null +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsErrorHandler.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.jms; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ErrorHandler; + +public class SampleJmsErrorHandler implements ErrorHandler { + + private static final Logger LOG = LoggerFactory.getLogger(SampleJmsErrorHandler.class); + + @Override + public void handleError(Throwable t) { + LOG.warn("In default jms error handler..."); + LOG.error("Error Message : {}", t.getMessage()); + } + +} diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java index 927762f05b..d3f09618fb 100644 --- a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleJmsMessageSender.java @@ -26,4 +26,8 @@ public class SampleJmsMessageSender { public void sendMessage(final Employee employee) { this.jmsTemplate.convertAndSend(employee); } + + public void sendTextMessage(String msg) { + this.jmsTemplate.send(queue, s -> s.createTextMessage(msg)); + } } diff --git a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java index f35c22e144..87627c47e7 100644 --- a/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java +++ b/spring-jms/src/main/java/com/baeldung/spring/jms/SampleListener.java @@ -27,6 +27,9 @@ public class SampleListener implements MessageListener { try { String msg = ((TextMessage) message).getText(); System.out.println("Received message: " + msg); + if (msg == null) { + throw new IllegalArgumentException("Null value received..."); + } } catch (JMSException ex) { throw new RuntimeException(ex); } @@ -37,4 +40,5 @@ public class SampleListener implements MessageListener { Map map = (Map) this.jmsTemplate.receiveAndConvert(); return new Employee((String) map.get("name"), (Integer) map.get("age")); } + } diff --git a/spring-jms/src/main/resources/applicationContext.xml b/spring-jms/src/main/resources/applicationContext.xml index 28bf848e59..97a90e0bf2 100644 --- a/spring-jms/src/main/resources/applicationContext.xml +++ b/spring-jms/src/main/resources/applicationContext.xml @@ -1,51 +1,48 @@ - - - - - - - - - - + + + + + + - - - + + + - + + + + + + + - - - + + + + + - - - - + + + + + - + - - - - - - - - - - - - - + + + + + + + diff --git a/spring-jms/src/test/java/com/baeldung/spring/jms/DefaultTextMessageSenderIntegrationTest.java b/spring-jms/src/test/java/com/baeldung/spring/jms/DefaultTextMessageSenderIntegrationTest.java index f87d26b144..f23ead4d69 100644 --- a/spring-jms/src/test/java/com/baeldung/spring/jms/DefaultTextMessageSenderIntegrationTest.java +++ b/spring-jms/src/test/java/com/baeldung/spring/jms/DefaultTextMessageSenderIntegrationTest.java @@ -8,12 +8,14 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class DefaultTextMessageSenderIntegrationTest { private static SampleJmsMessageSender messageProducer; + private static SampleListener messageListener; @SuppressWarnings("resource") @BeforeClass public static void setUp() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:EmbeddedActiveMQ.xml", "classpath:applicationContext.xml"); messageProducer = (SampleJmsMessageSender) applicationContext.getBean("SampleJmsMessageSender"); + messageListener = (SampleListener) applicationContext.getBean("messageListener"); } @Test @@ -21,4 +23,9 @@ public class DefaultTextMessageSenderIntegrationTest { messageProducer.simpleSend(); } + @Test + public void testSendTextMessage() { + messageProducer.sendTextMessage(null); + } + } From 7e2de11a5afaee971e4e54cf05540217263c1ff5 Mon Sep 17 00:00:00 2001 From: Rodolfo Felipe Date: Mon, 4 Mar 2019 00:36:23 -0400 Subject: [PATCH 212/496] BAEL-2448 Code examples for article. --- .../CollectionFilteringExamples.java | 51 +++++++++++++++++++ .../collection/filtering/Employee.java | 44 ++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 core-java-collections-list/src/main/java/com/baeldung/collection/filtering/CollectionFilteringExamples.java create mode 100644 core-java-collections-list/src/main/java/com/baeldung/collection/filtering/Employee.java diff --git a/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/CollectionFilteringExamples.java b/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/CollectionFilteringExamples.java new file mode 100644 index 0000000000..a7ab5840f7 --- /dev/null +++ b/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/CollectionFilteringExamples.java @@ -0,0 +1,51 @@ +package com.baeldung.collection.filtering; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Various filtering examples. + * + * @author Rodolfo Felipe + */ +public class CollectionFilteringExamples { + + private List buildEmployeeList() { + return Arrays.asList(new Employee(1, "Mike", 1), new Employee(2, "John", 1), new Employee(3, "Mary", 1), new Employee(4, "Joe", 2), new Employee(5, "Nicole", 2), new Employee(6, "Alice", 2), new Employee(7, "Bob", 3), new Employee(8, "Scarlett", 3)); + } + + private List employeeNameFilter() { + return Arrays.asList("Alice", "Mike", "Bob"); + } + + private List getFilteredEmployeeList() { + List filteredList = new ArrayList<>(); + for (Employee employee : buildEmployeeList()) { + for (String name : employeeNameFilter()) { + if (employee.getName() + .equalsIgnoreCase(name)) { + filteredList.add(employee); + } + } + } + return filteredList; + } + + private List getFilteredEmployeeListLambdaExample() { + return buildEmployeeList().stream() + .filter(employee -> employeeNameFilter().contains(employee.getName())) + .collect(Collectors.toList()); + } + + private List getFilteredEmployeeListLambdaExampleWithHashSetContains() { + Set nameFilterSet = employeeNameFilter().stream() + .collect(Collectors.toSet()); + return buildEmployeeList().stream() + .filter(employee -> nameFilterSet.contains(employee.getName())) + .collect(Collectors.toList()); + } + +} diff --git a/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/Employee.java b/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/Employee.java new file mode 100644 index 0000000000..2aa267b4dc --- /dev/null +++ b/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/Employee.java @@ -0,0 +1,44 @@ +package com.baeldung.collection.filtering; + +/** + * Java 8 Collection Filtering by List of Values base class. + * + * @author Rodolfo Felipe + */ +public class Employee { + + private Integer employeeNumber; + private String name; + private Integer departmentId; + + public Employee(Integer employeeNumber, String name, Integer departmentId) { + this.employeeNumber = employeeNumber; + this.name = name; + this.departmentId = departmentId; + } + + public Integer getEmployeeNumber() { + return employeeNumber; + } + + public void setEmployeeNumber(Integer employeeNumber) { + this.employeeNumber = employeeNumber; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(Integer departmentId) { + this.departmentId = departmentId; + } + +} From 834df022ec8b70993653978e9c7a17124e9e82c7 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 4 Mar 2019 18:16:42 +0800 Subject: [PATCH 213/496] Update README.md --- spring-5-reactive/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md index 119e57f256..ef2f7d07eb 100644 --- a/spring-5-reactive/README.md +++ b/spring-5-reactive/README.md @@ -7,7 +7,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Introduction to the Functional Web Framework in Spring 5](http://www.baeldung.com/spring-5-functional-web) - [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient) -- [Exploring the Spring 5 MVC URL Matching](http://www.baeldung.com/spring-5-mvc-url-matching) +- [Exploring the Spring 5 WebFlux URL Matching](http://www.baeldung.com/spring-5-mvc-url-matching) - [Reactive WebSockets with Spring 5](http://www.baeldung.com/spring-5-reactive-websockets) - [Spring Webflux Filters](http://www.baeldung.com/spring-webflux-filters) - [How to Set a Header on a Response with Spring 5](http://www.baeldung.com/spring-response-header) From 8cb3b8d8dcc9ee2f09152cc836af78212f25e388 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:28:17 +0530 Subject: [PATCH 214/496] Back-link added --- core-java-collections-list/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md index 3a4a7c69e8..b4e5a31f20 100644 --- a/core-java-collections-list/README.md +++ b/core-java-collections-list/README.md @@ -28,3 +28,4 @@ - [Intersection of Two Lists in Java](https://www.baeldung.com/java-lists-intersection) - [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) - [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal) +- [List of Primitive Integer Values in Java](https://www.baeldung.com/java-list-primitive-int) From e7503db1e798cc876d0eb09263dcf0b61c1fcc51 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:31:22 +0530 Subject: [PATCH 215/496] Back-link added --- java-strings/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-strings/README.md b/java-strings/README.md index 1ab5e098f6..3c401b4102 100644 --- a/java-strings/README.md +++ b/java-strings/README.md @@ -53,3 +53,4 @@ - [Java String Interview Questions and Answers](https://www.baeldung.com/java-string-interview-questions) - [Check if a String is a Pangram in Java](https://www.baeldung.com/java-string-pangram) - [Check If a String Contains Multiple Keywords](https://www.baeldung.com/string-contains-multiple-words) +- [Common String Operations in Java](https://www.baeldung.com/java-string-operations) From d3090e250855681cf68aa2a639137203a918b9d1 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:35:03 +0530 Subject: [PATCH 216/496] Back-link added --- core-java-lang/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-lang/README.md b/core-java-lang/README.md index c1c22caf6c..eaedc93eed 100644 --- a/core-java-lang/README.md +++ b/core-java-lang/README.md @@ -41,3 +41,4 @@ - [Java Interfaces](https://www.baeldung.com/java-interfaces) - [Attaching Values to Java Enum](https://www.baeldung.com/java-enum-values) - [Variable Scope in Java](https://www.baeldung.com/java-variable-scope) +- [Java Classes and Objects](https://www.baeldung.com/java-classes-objects) From aa80b07e8071713d01eec0aa9cfd31d49e72bc9a Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:36:45 +0530 Subject: [PATCH 217/496] Back-link added --- core-java-8/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-8/README.md b/core-java-8/README.md index 892dc71f76..540a5f677f 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -38,3 +38,4 @@ - [Java @SafeVarargs Annotation](https://www.baeldung.com/java-safevarargs) - [Java @Deprecated Annotation](https://www.baeldung.com/java-deprecated) - [Java 8 Predicate Chain](https://www.baeldung.com/java-predicate-chain) +- [Method References in Java](https://www.baeldung.com/java-method-references) From a8fb9250bf2e7e06ef0e39fb0cdb862d46cd0b1f Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:38:13 +0530 Subject: [PATCH 218/496] Back-link added --- spring-boot-mvc/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-mvc/README.md b/spring-boot-mvc/README.md index 0e1ac5a8ce..d5a39cdc9f 100644 --- a/spring-boot-mvc/README.md +++ b/spring-boot-mvc/README.md @@ -11,3 +11,4 @@ - [Cache Eviction in Spring Boot](https://www.baeldung.com/spring-boot-evict-cache) - [Setting Up Swagger 2 with a Spring REST API](http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api) - [Conditionally Enable Scheduled Jobs in Spring](https://www.baeldung.com/spring-scheduled-enabled-conditionally) +- [Accessing Spring MVC Model Objects in JavaScript](https://www.baeldung.com/spring-mvc-model-objects-js) From ab33ec149ea2dc72c585be797291d5d47747cdc0 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:41:20 +0530 Subject: [PATCH 219/496] Back-link added --- guice/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/guice/README.md b/guice/README.md index d1bd1ff883..77c788c363 100644 --- a/guice/README.md +++ b/guice/README.md @@ -2,3 +2,4 @@ ### Relevant Articles - [Guide to Google Guice](http://www.baeldung.com/guice) +- [Guice vs Spring – Dependency Injection](https://www.baeldung.com/guice-spring-dependency-injection) From 17fad4c738237d86092779dc7cc4674b3344e44e Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:44:10 +0530 Subject: [PATCH 220/496] Back-link added --- core-java-lang-oop/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-lang-oop/README.md b/core-java-lang-oop/README.md index bbc3d26c99..200415fe21 100644 --- a/core-java-lang-oop/README.md +++ b/core-java-lang-oop/README.md @@ -22,3 +22,4 @@ - [Inheritance and Composition (Is-a vs Has-a relationship) in Java](http://www.baeldung.com/java-inheritance-composition) - [A Guide to Constructors in Java](https://www.baeldung.com/java-constructors) - [Java equals() and hashCode() Contracts](https://www.baeldung.com/java-equals-hashcode-contracts) +- [Marker Interfaces in Java](https://www.baeldung.com/java-marker-interfaces) From 1df138e5099eb80a14b217508b922c1d612ea7d8 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:47:01 +0530 Subject: [PATCH 221/496] Back-link added --- core-java/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java/README.md b/core-java/README.md index 1143604eac..67538a3895 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -50,3 +50,4 @@ - [Using Curl in Java](https://www.baeldung.com/java-curl) - [Finding Leap Years in Java](https://www.baeldung.com/java-leap-year) - [Java Bitwise Operators](https://www.baeldung.com/java-bitwise-operators) +- [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) From b5a73e7252845a3685986526feec8a4ab1f1b8a3 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:49:02 +0530 Subject: [PATCH 222/496] Back-link added --- core-groovy/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-groovy/README.md b/core-groovy/README.md index 71788acdb7..f1a1161875 100644 --- a/core-groovy/README.md +++ b/core-groovy/README.md @@ -4,3 +4,4 @@ - [JDBC with Groovy](http://www.baeldung.com/jdbc-groovy) - [Working with JSON in Groovy](http://www.baeldung.com/groovy-json) +- [Reading a File in Groovy](https://www.baeldung.com/groovy-file-read) From 5bc15c387d0989ddb9bb1adb8078faf86f511fc4 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:52:30 +0530 Subject: [PATCH 223/496] Back-link added --- spring-security-mvc-jsonview/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 spring-security-mvc-jsonview/README.md diff --git a/spring-security-mvc-jsonview/README.md b/spring-security-mvc-jsonview/README.md new file mode 100644 index 0000000000..35c806e856 --- /dev/null +++ b/spring-security-mvc-jsonview/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Filtering Jackson JSON Output Based on Spring Security Role](https://www.baeldung.com/spring-security-role-filter-json) From 178e3aa0f26cee2c68e97cc63ec4ff6ec40cbd2d Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:54:04 +0530 Subject: [PATCH 224/496] Back-link added --- core-java-collections/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-collections/README.md b/core-java-collections/README.md index 710be31a08..80d4385c45 100644 --- a/core-java-collections/README.md +++ b/core-java-collections/README.md @@ -32,3 +32,4 @@ - [A Guide to Iterator in Java](http://www.baeldung.com/java-iterator) - [Differences Between HashMap and Hashtable](https://www.baeldung.com/hashmap-hashtable-differences) - [Java ArrayList vs Vector](https://www.baeldung.com/java-arraylist-vs-vector) +- [Defining a Char Stack in Java](https://www.baeldung.com/java-char-stack) From e299681c32a956ed5d4e4e67e9e788a3e78363e5 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 4 Mar 2019 19:24:11 +0800 Subject: [PATCH 225/496] Update README.md --- core-java-networking/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-networking/README.md b/core-java-networking/README.md index faeeadab24..f6ce44d72f 100644 --- a/core-java-networking/README.md +++ b/core-java-networking/README.md @@ -9,7 +9,7 @@ - [A Guide To UDP In Java](http://www.baeldung.com/udp-in-java) - [Sending Emails with Java](http://www.baeldung.com/java-email) - [A Guide To HTTP Cookies In Java](http://www.baeldung.com/cookies-java) -- [A Simple Guide to the Java URL](http://www.baeldung.com/java-url) +- [A Guide to the Java URL](http://www.baeldung.com/java-url) - [Working with Network Interfaces in Java](http://www.baeldung.com/java-network-interfaces) - [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets) - [Guide to Java URL Encoding/Decoding](http://www.baeldung.com/java-url-encoding-decoding) From 1e2032b96cbdee9fcecb4a1856c7b2fe7d983c3f Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 16:55:58 +0530 Subject: [PATCH 226/496] Back-link added --- core-kotlin/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 6ee79b2a2e..1a7ecd34e1 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -52,3 +52,4 @@ - [Inline Classes in Kotlin](https://www.baeldung.com/kotlin-inline-classes) - [Creating Java static final Equivalents in Kotlin](https://www.baeldung.com/kotlin-java-static-final) - [Nested forEach in Kotlin](https://www.baeldung.com/kotlin-nested-foreach) +- [Building DSLs in Kotlin](https://www.baeldung.com/kotlin-dsl) From b9914774480135413159479385af48611b9b194f Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:00:18 +0530 Subject: [PATCH 227/496] Back-Link added --- spring-boot-libraries/README.MD | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-libraries/README.MD b/spring-boot-libraries/README.MD index cc32ce8355..f3706e0fa4 100644 --- a/spring-boot-libraries/README.MD +++ b/spring-boot-libraries/README.MD @@ -4,3 +4,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [Guide to ShedLock with Spring](https://www.baeldung.com/shedlock-spring) +- [A Guide to the Problem Spring Web Library](https://www.baeldung.com/problem-spring-web) From f8ca54321733bc26e76d3bc649e7835afa29fe53 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:04:53 +0530 Subject: [PATCH 228/496] Back-link added --- spring-soap/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 spring-soap/README.md diff --git a/spring-soap/README.md b/spring-soap/README.md new file mode 100644 index 0000000000..8d96350e1e --- /dev/null +++ b/spring-soap/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Creating a SOAP Web Service with Spring](https://www.baeldung.com/spring-boot-soap-web-service) From f956a00fdd5cb59fa7e126f031456a2e11b39fec Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:05:55 +0530 Subject: [PATCH 229/496] Back-link added --- persistence-modules/hibernate5/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/hibernate5/README.md b/persistence-modules/hibernate5/README.md index a4e95a9062..8fc8a433e8 100644 --- a/persistence-modules/hibernate5/README.md +++ b/persistence-modules/hibernate5/README.md @@ -30,3 +30,4 @@ - [Using c3p0 with Hibernate](https://www.baeldung.com/hibernate-c3p0) - [Persist a JSON Object Using Hibernate](https://www.baeldung.com/hibernate-persist-json-object) - [Common Hibernate Exceptions](https://www.baeldung.com/hibernate-exceptions) +- [Hibernate Aggregate Functions](https://www.baeldung.com/hibernate-aggregate-functions) From aa4a20b4a899843055c1876964d2d2300257b315 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:07:30 +0530 Subject: [PATCH 230/496] Back-link added --- persistence-modules/hibernate5/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/hibernate5/README.md b/persistence-modules/hibernate5/README.md index 8fc8a433e8..026a5feb86 100644 --- a/persistence-modules/hibernate5/README.md +++ b/persistence-modules/hibernate5/README.md @@ -31,3 +31,4 @@ - [Persist a JSON Object Using Hibernate](https://www.baeldung.com/hibernate-persist-json-object) - [Common Hibernate Exceptions](https://www.baeldung.com/hibernate-exceptions) - [Hibernate Aggregate Functions](https://www.baeldung.com/hibernate-aggregate-functions) +- [Hibernate Query Plan Cache](https://www.baeldung.com/hibernate-query-plan-cache) From 5e30bafb53e1ee1bf4318900ffe6ed1bbedc20f9 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:14:03 +0530 Subject: [PATCH 231/496] Back-link added --- core-java-9/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-9/README.md b/core-java-9/README.md index d9586ba684..d24106cc8f 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -27,3 +27,4 @@ - [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api) - [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) - [Immutable Set in Java](https://www.baeldung.com/java-immutable-set) +- [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) From 70d2bb2c91c4168d0f6c91a6dc1f284cfc0b716e Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:15:06 +0530 Subject: [PATCH 232/496] Back-link added --- core-kotlin/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 1a7ecd34e1..64ecd73b1c 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -53,3 +53,4 @@ - [Creating Java static final Equivalents in Kotlin](https://www.baeldung.com/kotlin-java-static-final) - [Nested forEach in Kotlin](https://www.baeldung.com/kotlin-nested-foreach) - [Building DSLs in Kotlin](https://www.baeldung.com/kotlin-dsl) +- [Static Methods Behavior in Kotlin](https://www.baeldung.com/kotlin-static-methods) From 00b9b9e9b95adc11130c90f98f20f0b74b60b247 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:17:19 +0530 Subject: [PATCH 233/496] Back-link added --- persistence-modules/spring-data-jpa/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md index 739031ff5e..e629a464df 100644 --- a/persistence-modules/spring-data-jpa/README.md +++ b/persistence-modules/spring-data-jpa/README.md @@ -20,6 +20,7 @@ - [INSERT Statement in JPA](https://www.baeldung.com/jpa-insert) - [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) - [Spring Data JPA Query by Example](https://www.baeldung.com/spring-data-query-by-example) +- [DB Integration Tests with Spring Boot and Testcontainers](https://www.baeldung.com/spring-boot-testcontainers-integration-test) ### Eclipse Config After importing the project into Eclipse, you may see the following error: From 140850225e44001cb096ec6bbbe2e1f3b22d6661 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:18:18 +0530 Subject: [PATCH 234/496] Back-link added --- core-groovy/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-groovy/README.md b/core-groovy/README.md index f1a1161875..fde7f33f86 100644 --- a/core-groovy/README.md +++ b/core-groovy/README.md @@ -5,3 +5,4 @@ - [JDBC with Groovy](http://www.baeldung.com/jdbc-groovy) - [Working with JSON in Groovy](http://www.baeldung.com/groovy-json) - [Reading a File in Groovy](https://www.baeldung.com/groovy-file-read) +- [Types of Strings in Groovy](https://www.baeldung.com/groovy-strings) From 8fbe21c0eb1b37aed4aa33be90c8a30ef104b721 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:19:13 +0530 Subject: [PATCH 235/496] Back-link added --- core-java-9/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-9/README.md b/core-java-9/README.md index d24106cc8f..7e256d5c7e 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -28,3 +28,4 @@ - [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) - [Immutable Set in Java](https://www.baeldung.com/java-immutable-set) - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) +- [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation) From 55b93c5c52587a53795b5568b76c02b5cf36230f Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:20:11 +0530 Subject: [PATCH 236/496] Back-link added --- core-groovy/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-groovy/README.md b/core-groovy/README.md index fde7f33f86..6e385d528f 100644 --- a/core-groovy/README.md +++ b/core-groovy/README.md @@ -6,3 +6,4 @@ - [Working with JSON in Groovy](http://www.baeldung.com/groovy-json) - [Reading a File in Groovy](https://www.baeldung.com/groovy-file-read) - [Types of Strings in Groovy](https://www.baeldung.com/groovy-strings) +- [A Quick Guide to Iterating a Map in Groovy](https://www.baeldung.com/groovy-map-iterating) From b4a1434ad6eaefcf04a8942d8df4e55b75823b4a Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:21:01 +0530 Subject: [PATCH 237/496] Back-link added --- core-java-collections-list/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md index b4e5a31f20..598d8331d0 100644 --- a/core-java-collections-list/README.md +++ b/core-java-collections-list/README.md @@ -29,3 +29,4 @@ - [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) - [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal) - [List of Primitive Integer Values in Java](https://www.baeldung.com/java-list-primitive-int) +- [Performance Comparison of Primitive Lists in Java](https://www.baeldung.com/java-list-primitive-performance) From bb2003ca8ef2226e62d7bc3b8de0c30cc3278c4c Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:21:57 +0530 Subject: [PATCH 238/496] Back-link added --- core-groovy/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-groovy/README.md b/core-groovy/README.md index 6e385d528f..ec2fcfa574 100644 --- a/core-groovy/README.md +++ b/core-groovy/README.md @@ -7,3 +7,4 @@ - [Reading a File in Groovy](https://www.baeldung.com/groovy-file-read) - [Types of Strings in Groovy](https://www.baeldung.com/groovy-strings) - [A Quick Guide to Iterating a Map in Groovy](https://www.baeldung.com/groovy-map-iterating) +- [An Introduction to Traits in Groovy](https://www.baeldung.com/groovy-traits) From 5f9665ab6ecb43da5ef64b58348f6b5021a23ed1 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:22:50 +0530 Subject: [PATCH 239/496] Back-link added --- spring-mvc-simple/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-mvc-simple/README.md b/spring-mvc-simple/README.md index 755e0932fc..cd4ad5aba2 100644 --- a/spring-mvc-simple/README.md +++ b/spring-mvc-simple/README.md @@ -8,3 +8,4 @@ - [Guide to Spring Email](http://www.baeldung.com/spring-email) - [Request Method Not Supported (405) in Spring](https://www.baeldung.com/spring-request-method-not-supported-405) - [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param) +- [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable) From f6d4d8c4602e0e84cc577f3ce750c256e4f49ad9 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:23:41 +0530 Subject: [PATCH 240/496] Back-link added --- json/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/json/README.md b/json/README.md index 2e253a4ae9..24b25a5b12 100644 --- a/json/README.md +++ b/json/README.md @@ -11,3 +11,4 @@ - [Overview of JSON Pointer](https://www.baeldung.com/json-pointer) - [Introduction to the JSON Binding API (JSR 367) in Java](http://www.baeldung.com/java-json-binding-api) - [Get a Value by Key in a JSONArray](https://www.baeldung.com/java-jsonarray-get-value-by-key) +- [Iterating Over an Instance of org.json.JSONObject](https://www.baeldung.com/jsonobject-iteration) From 58389b2a86b5c87abeaa540290aafa4303b21a11 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:24:40 +0530 Subject: [PATCH 241/496] Back-link added --- json/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/json/README.md b/json/README.md index 24b25a5b12..c0ca4b00ef 100644 --- a/json/README.md +++ b/json/README.md @@ -12,3 +12,4 @@ - [Introduction to the JSON Binding API (JSR 367) in Java](http://www.baeldung.com/java-json-binding-api) - [Get a Value by Key in a JSONArray](https://www.baeldung.com/java-jsonarray-get-value-by-key) - [Iterating Over an Instance of org.json.JSONObject](https://www.baeldung.com/jsonobject-iteration) +- [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections) From 6afbc3086f2e7403e6a935842e2c3d52d01a134d Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:27:04 +0530 Subject: [PATCH 242/496] Back-link added --- software-security/sql-injection-samples/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 software-security/sql-injection-samples/README.md diff --git a/software-security/sql-injection-samples/README.md b/software-security/sql-injection-samples/README.md new file mode 100644 index 0000000000..7a077074ac --- /dev/null +++ b/software-security/sql-injection-samples/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [SQL Injection and How to Prevent It?](https://www.baeldung.com/sql-injection) From 0f2e3da7d465fd457c7f94c849644cc3a4ebe114 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:27:39 +0530 Subject: [PATCH 243/496] Back-link added --- core-kotlin-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-kotlin-2/README.md b/core-kotlin-2/README.md index 6aabd71a6c..8d22c4f1a8 100644 --- a/core-kotlin-2/README.md +++ b/core-kotlin-2/README.md @@ -1,3 +1,4 @@ ## Relevant articles: - [Void Type in Kotlin](https://www.baeldung.com/kotlin-void-type) +- [How to use Kotlin Range Expressions](https://www.baeldung.com/kotlin-ranges) From 3ede9262f6fa6e1a8f49e3e24c24f9d34cd9979e Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:28:52 +0530 Subject: [PATCH 244/496] Back-link added --- jhipster/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/jhipster/README.md b/jhipster/README.md index 91ba54bf60..289bfac754 100644 --- a/jhipster/README.md +++ b/jhipster/README.md @@ -3,3 +3,4 @@ - [JHipster with a Microservice Architecture](http://www.baeldung.com/jhipster-microservices) - [Intro to JHipster](http://www.baeldung.com/jhipster) - [Building a Basic UAA-Secured JHipster Microservice](https://www.baeldung.com/jhipster-uaa-secured-micro-service) +- [Creating New Roles and Authorities in JHipster](https://www.baeldung.com/jhipster-new-roles) From 04638627a7c15f23edfea156a531f751e6a6e8e1 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:29:42 +0530 Subject: [PATCH 245/496] Back-link added --- persistence-modules/spring-data-jpa/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md index e629a464df..9512ad336d 100644 --- a/persistence-modules/spring-data-jpa/README.md +++ b/persistence-modules/spring-data-jpa/README.md @@ -21,6 +21,7 @@ - [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) - [Spring Data JPA Query by Example](https://www.baeldung.com/spring-data-query-by-example) - [DB Integration Tests with Spring Boot and Testcontainers](https://www.baeldung.com/spring-boot-testcontainers-integration-test) +- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) ### Eclipse Config After importing the project into Eclipse, you may see the following error: From be2d3ce59a317cd4dfeeeed459c49383ba79357b Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:30:56 +0530 Subject: [PATCH 246/496] Back-link added --- ratpack/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ratpack/README.md b/ratpack/README.md index dded42fab6..14bc3f6c74 100644 --- a/ratpack/README.md +++ b/ratpack/README.md @@ -5,3 +5,4 @@ - [Ratpack Integration with Spring Boot](http://www.baeldung.com/ratpack-spring-boot) - [Ratpack with Hystrix](http://www.baeldung.com/ratpack-hystrix) - [Ratpack HTTP Client](https://www.baeldung.com/ratpack-http-client) +- [Ratpack with RxJava](https://www.baeldung.com/ratpack-rxjava) From 10a395f64e1cb6d9649fc17ae02d422ca374e89c Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:31:49 +0530 Subject: [PATCH 247/496] Back-link added --- maven/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/maven/README.md b/maven/README.md index 1c0e50f95a..1352a2a10f 100644 --- a/maven/README.md +++ b/maven/README.md @@ -14,3 +14,4 @@ - [Apache Maven Tutorial](https://www.baeldung.com/maven) - [Use the Latest Version of a Dependency in Maven](https://www.baeldung.com/maven-dependency-latest-version) - [Multi-Module Project with Maven](https://www.baeldung.com/maven-multi-module) +- [Maven Enforcer Plugin](https://www.baeldung.com/maven-enforcer-plugin) From 3f6b909ab8d6083fa1bdb35af05aa53505fa2c69 Mon Sep 17 00:00:00 2001 From: collaboratewithakash <38683470+collaboratewithakash@users.noreply.github.com> Date: Mon, 4 Mar 2019 17:33:17 +0530 Subject: [PATCH 248/496] Back-link added --- libraries/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/README.md b/libraries/README.md index 378317778e..57f22631f1 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -66,6 +66,7 @@ - [Implementing a FTP-Client in Java](http://www.baeldung.com/java-ftp-client) - [Introduction to Functional Java](https://www.baeldung.com/java-functional-library) - [Intro to Derive4J](https://www.baeldung.com/derive4j) +- [A Guide to the Reflections Library](https://www.baeldung.com/reflections-library) The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own. From c2cb4d4bc081d678f4a8fc3bdcd7a8e86c36f761 Mon Sep 17 00:00:00 2001 From: Ganesh Pagade Date: Tue, 5 Mar 2019 00:01:05 +0530 Subject: [PATCH 249/496] gson advanced list examples --- .../org/baeldung/gson/entities/Animal.java | 5 + .../java/org/baeldung/gson/entities/Cow.java | 19 ++ .../java/org/baeldung/gson/entities/Dog.java | 18 ++ .../org/baeldung/gson/entities/MyClass.java | 37 +++ .../serialization/AnimalDeserializer.java | 35 +++ .../gson/advance/GsonAdvanceUnitTest.java | 110 ++++++++ .../advance/RuntimeTypeAdapterFactory.java | 265 ++++++++++++++++++ 7 files changed, 489 insertions(+) create mode 100644 gson/src/main/java/org/baeldung/gson/entities/Animal.java create mode 100644 gson/src/main/java/org/baeldung/gson/entities/Cow.java create mode 100644 gson/src/main/java/org/baeldung/gson/entities/Dog.java create mode 100644 gson/src/main/java/org/baeldung/gson/entities/MyClass.java create mode 100644 gson/src/main/java/org/baeldung/gson/serialization/AnimalDeserializer.java create mode 100644 gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java create mode 100644 gson/src/test/java/org/baeldung/gson/advance/RuntimeTypeAdapterFactory.java diff --git a/gson/src/main/java/org/baeldung/gson/entities/Animal.java b/gson/src/main/java/org/baeldung/gson/entities/Animal.java new file mode 100644 index 0000000000..2eec5f8704 --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/entities/Animal.java @@ -0,0 +1,5 @@ +package org.baeldung.gson.entities; + +public abstract class Animal { + public String type = "Animal"; +} diff --git a/gson/src/main/java/org/baeldung/gson/entities/Cow.java b/gson/src/main/java/org/baeldung/gson/entities/Cow.java new file mode 100644 index 0000000000..020bcd5860 --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/entities/Cow.java @@ -0,0 +1,19 @@ +package org.baeldung.gson.entities; + +public class Cow extends Animal { + private String breed; + + public Cow() { + breed = "Jersey"; + type = "Cow"; + } + + public String getBreed() { + return breed; + } + + public void setBreed(String breed) { + this.breed = breed; + } +} + diff --git a/gson/src/main/java/org/baeldung/gson/entities/Dog.java b/gson/src/main/java/org/baeldung/gson/entities/Dog.java new file mode 100644 index 0000000000..042d73adcf --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/entities/Dog.java @@ -0,0 +1,18 @@ +package org.baeldung.gson.entities; + +public class Dog extends Animal { + private String petName; + + public Dog() { + petName = "Milo"; + type = "Dog"; + } + + public String getPetName() { + return petName; + } + + public void setPetName(String petName) { + this.petName = petName; + } +} diff --git a/gson/src/main/java/org/baeldung/gson/entities/MyClass.java b/gson/src/main/java/org/baeldung/gson/entities/MyClass.java new file mode 100644 index 0000000000..86e14985da --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/entities/MyClass.java @@ -0,0 +1,37 @@ +package org.baeldung.gson.entities; + +public class MyClass { + private int id; + private String[] strings; + + public MyClass() { + id = 1; + strings = new String[] { "a", "b" }; + } + + + // @Override + // public String toString() { + // return "{" + + // "id=" + id + + // ", name='" + name + '\'' + + // ", strings=" + Arrays.toString(strings) + + // '}'; + // } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String[] getStrings() { + return strings; + } + + public void setStrings(String[] strings) { + this.strings = strings; + } +} diff --git a/gson/src/main/java/org/baeldung/gson/serialization/AnimalDeserializer.java b/gson/src/main/java/org/baeldung/gson/serialization/AnimalDeserializer.java new file mode 100644 index 0000000000..9dcef0e10b --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/serialization/AnimalDeserializer.java @@ -0,0 +1,35 @@ +package org.baeldung.gson.serialization; + +import com.google.gson.Gson; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; +import org.baeldung.gson.entities.Animal; + +public class AnimalDeserializer implements JsonDeserializer { + private String animalTypeElementName; + private Gson gson; + private Map> animalTypeRegistry; + + public AnimalDeserializer(String animalTypeElementName) { + this.animalTypeElementName = animalTypeElementName; + this.gson = new Gson(); + this.animalTypeRegistry = new HashMap<>(); + } + + public void registerBarnType(String animalTypeName, Class animalType) { + animalTypeRegistry.put(animalTypeName, animalType); + } + + public Animal deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { + JsonObject animalObject = json.getAsJsonObject(); + JsonElement animalTypeElement = animalObject.get(animalTypeElementName); + + Class animalType = animalTypeRegistry.get(animalTypeElement.getAsString()); + return gson.fromJson(animalObject, animalType); + } +} \ No newline at end of file diff --git a/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java b/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java new file mode 100644 index 0000000000..7032dde1ce --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java @@ -0,0 +1,110 @@ +package org.baeldung.gson.advance; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import org.baeldung.gson.entities.Animal; +import org.baeldung.gson.entities.Cow; +import org.baeldung.gson.entities.Dog; +import org.baeldung.gson.entities.MyClass; +import org.baeldung.gson.serialization.AnimalDeserializer; +import org.junit.Test; + +public class GsonAdvanceUnitTest { + + @Test public void givenListOfMyClass_whenSerializing_thenCorrect() { + List list = new ArrayList<>(); + list.add(new MyClass()); + list.add(new MyClass()); + + Gson gson = new Gson(); + String jsonString = gson.toJson(list); + String expectedString = "[{\"id\":1,\"strings\":[\"a\",\"b\"]},{\"id\":1,\"strings\":[\"a\",\"b\"]}]"; + + assertEquals(expectedString, jsonString); + } + + @Test(expected = ClassCastException.class) + public void givenJsonString_whenIncorrectDeserializing_thenThrowClassCastException() { + String inputString = "[{\"id\":1,\"strings\":[\"a\",\"b\"]},{\"id\":1,\"strings\":[\"a\",\"b\"]}]"; + + Gson gson = new Gson(); + List list = gson.fromJson(inputString, ArrayList.class); + + assertEquals(2, list.size()); + int id = list.get(0).getId(); + } + + @Test public void givenJsonString_whenDeserializing_thenReturnListOfMyClass() { + String inputString = "[{\"id\":1,\"strings\":[\"a\",\"b\"]},{\"id\":1,\"strings\":[\"a\",\"b\"]}]"; + Type listOfMyClassObject = new TypeToken>() {}.getType(); + + Gson gson = new Gson(); + List list = gson.fromJson(inputString, listOfMyClassObject); + + assertEquals(2, list.size()); + assertEquals(1, list.get(0).getId()); + } + + @Test public void givenPolymorphicList_whenSerializeWithTypeAdapter_thenCorrect() { + String expectedString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]"; + + List inList = new ArrayList<>(); + inList.add(new Dog()); + inList.add(new Cow()); + + String jsonString = new Gson().toJson(inList); + + assertEquals(expectedString, jsonString); + } + + @Test public void givenPolymorphicList_whenDeserializeWithTypeAdapter_thenCorrect() { + String inputString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]"; + + AnimalDeserializer deserializer = new AnimalDeserializer("type"); + deserializer.registerBarnType("Dog", Dog.class); + deserializer.registerBarnType("Cow", Cow.class); + Gson gson = new GsonBuilder() + .registerTypeAdapter(Animal.class, deserializer) + .create(); + + List outList = gson.fromJson(inputString, new TypeToken>(){}.getType()); + + assertEquals(2, outList.size()); + assertTrue(outList.get(0) instanceof Dog); + } + + @Test public void givenPolymorphicList_whenSerializeWithRuntimeTypeAdapter_thenCorrect() { + String expectedString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]"; + + List inList = new ArrayList<>(); + inList.add(new Dog()); + inList.add(new Cow()); + String jsonString = new Gson().toJson(inList); + + assertEquals(expectedString, jsonString); + } + + @Test public void givenPolymorphicList_whenDeserializeWithRuntimeTypeAdapter_thenCorrect() { + String inputString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]"; + + Type listOfAnimals = new TypeToken>() {}.getType(); + + RuntimeTypeAdapterFactory adapter = RuntimeTypeAdapterFactory.of(Animal.class) + .registerSubtype(Dog.class) + .registerSubtype(Cow.class); + + Gson gson = new GsonBuilder().registerTypeAdapterFactory(adapter).create(); + + List outList = gson.fromJson(inputString, listOfAnimals); + + assertEquals(2, outList.size()); + assertTrue(outList.get(0) instanceof Dog); + } +} \ No newline at end of file diff --git a/gson/src/test/java/org/baeldung/gson/advance/RuntimeTypeAdapterFactory.java b/gson/src/test/java/org/baeldung/gson/advance/RuntimeTypeAdapterFactory.java new file mode 100644 index 0000000000..739dd889c7 --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/advance/RuntimeTypeAdapterFactory.java @@ -0,0 +1,265 @@ +package org.baeldung.gson.advance; + +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.Streams; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +/** + * Adapts values whose runtime type may differ from their declaration type. This + * is necessary when a field's type is not the same type that GSON should create + * when deserializing that field. For example, consider these types: + *
   {@code
+ *   abstract class Shape {
+ *     int x;
+ *     int y;
+ *   }
+ *   class Circle extends Shape {
+ *     int radius;
+ *   }
+ *   class Rectangle extends Shape {
+ *     int width;
+ *     int height;
+ *   }
+ *   class Diamond extends Shape {
+ *     int width;
+ *     int height;
+ *   }
+ *   class Drawing {
+ *     Shape bottomShape;
+ *     Shape topShape;
+ *   }
+ * }
+ *

Without additional type information, the serialized JSON is ambiguous. Is + * the bottom shape in this drawing a rectangle or a diamond?

   {@code
+ *   {
+ *     "bottomShape": {
+ *       "width": 10,
+ *       "height": 5,
+ *       "x": 0,
+ *       "y": 0
+ *     },
+ *     "topShape": {
+ *       "radius": 2,
+ *       "x": 4,
+ *       "y": 1
+ *     }
+ *   }}
+ * This class addresses this problem by adding type information to the + * serialized JSON and honoring that type information when the JSON is + * deserialized:
   {@code
+ *   {
+ *     "bottomShape": {
+ *       "type": "Diamond",
+ *       "width": 10,
+ *       "height": 5,
+ *       "x": 0,
+ *       "y": 0
+ *     },
+ *     "topShape": {
+ *       "type": "Circle",
+ *       "radius": 2,
+ *       "x": 4,
+ *       "y": 1
+ *     }
+ *   }}
+ * Both the type field name ({@code "type"}) and the type labels ({@code + * "Rectangle"}) are configurable. + * + *

Registering Types

+ * Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field + * name to the {@link #of} factory method. If you don't supply an explicit type + * field name, {@code "type"} will be used.
   {@code
+ *   RuntimeTypeAdapterFactory shapeAdapterFactory
+ *       = RuntimeTypeAdapterFactory.of(Shape.class, "type");
+ * }
+ * Next register all of your subtypes. Every subtype must be explicitly + * registered. This protects your application from injection attacks. If you + * don't supply an explicit type label, the type's simple name will be used. + *
   {@code
+ *   shapeAdapterFactory.registerSubtype(Rectangle.class, "Rectangle");
+ *   shapeAdapterFactory.registerSubtype(Circle.class, "Circle");
+ *   shapeAdapterFactory.registerSubtype(Diamond.class, "Diamond");
+ * }
+ * Finally, register the type adapter factory in your application's GSON builder: + *
   {@code
+ *   Gson gson = new GsonBuilder()
+ *       .registerTypeAdapterFactory(shapeAdapterFactory)
+ *       .create();
+ * }
+ * Like {@code GsonBuilder}, this API supports chaining:
   {@code
+ *   RuntimeTypeAdapterFactory shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
+ *       .registerSubtype(Rectangle.class)
+ *       .registerSubtype(Circle.class)
+ *       .registerSubtype(Diamond.class);
+ * }
+ */ +public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory { + private final Class baseType; + private final String typeFieldName; + private final Map> labelToSubtype = new LinkedHashMap>(); + private final Map, String> subtypeToLabel = new LinkedHashMap, String>(); + private final boolean maintainType; + + private RuntimeTypeAdapterFactory(Class baseType, String typeFieldName, boolean maintainType) { + if (typeFieldName == null || baseType == null) { + throw new NullPointerException(); + } + this.baseType = baseType; + this.typeFieldName = typeFieldName; + this.maintainType = maintainType; + } + + /** + * Creates a new runtime type adapter using for {@code baseType} using {@code + * typeFieldName} as the type field name. Type field names are case sensitive. + * {@code maintainType} flag decide if the type will be stored in pojo or not. + */ + public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName, boolean maintainType) { + return new RuntimeTypeAdapterFactory(baseType, typeFieldName, maintainType); + } + + /** + * Creates a new runtime type adapter using for {@code baseType} using {@code + * typeFieldName} as the type field name. Type field names are case sensitive. + */ + public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName) { + return new RuntimeTypeAdapterFactory(baseType, typeFieldName, false); + } + + /** + * Creates a new runtime type adapter for {@code baseType} using {@code "type"} as + * the type field name. + */ + public static RuntimeTypeAdapterFactory of(Class baseType) { + return new RuntimeTypeAdapterFactory(baseType, "type", false); + } + + /** + * Registers {@code type} identified by {@code label}. Labels are case + * sensitive. + * + * @throws IllegalArgumentException if either {@code type} or {@code label} + * have already been registered on this type adapter. + */ + public RuntimeTypeAdapterFactory registerSubtype(Class type, String label) { + if (type == null || label == null) { + throw new NullPointerException(); + } + if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) { + throw new IllegalArgumentException("types and labels must be unique"); + } + labelToSubtype.put(label, type); + subtypeToLabel.put(type, label); + return this; + } + + /** + * Registers {@code type} identified by its {@link Class#getSimpleName simple + * name}. Labels are case sensitive. + * + * @throws IllegalArgumentException if either {@code type} or its simple name + * have already been registered on this type adapter. + */ + public RuntimeTypeAdapterFactory registerSubtype(Class type) { + return registerSubtype(type, type.getSimpleName()); + } + + public TypeAdapter create(Gson gson, TypeToken type) { + if (type.getRawType() != baseType) { + return null; + } + + final Map> labelToDelegate + = new LinkedHashMap>(); + final Map, TypeAdapter> subtypeToDelegate + = new LinkedHashMap, TypeAdapter>(); + for (Map.Entry> entry : labelToSubtype.entrySet()) { + TypeAdapter delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue())); + labelToDelegate.put(entry.getKey(), delegate); + subtypeToDelegate.put(entry.getValue(), delegate); + } + + return new TypeAdapter() { + @Override public R read(JsonReader in) throws IOException { + JsonElement jsonElement = Streams.parse(in); + JsonElement labelJsonElement; + if (maintainType) { + labelJsonElement = jsonElement.getAsJsonObject().get(typeFieldName); + } else { + labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName); + } + + if (labelJsonElement == null) { + throw new JsonParseException("cannot deserialize " + baseType + + " because it does not define a field named " + typeFieldName); + } + String label = labelJsonElement.getAsString(); + @SuppressWarnings("unchecked") // registration requires that subtype extends T + TypeAdapter delegate = (TypeAdapter) labelToDelegate.get(label); + if (delegate == null) { + throw new JsonParseException("cannot deserialize " + baseType + " subtype named " + + label + "; did you forget to register a subtype?"); + } + return delegate.fromJsonTree(jsonElement); + } + + @Override public void write(JsonWriter out, R value) throws IOException { + Class srcType = value.getClass(); + String label = subtypeToLabel.get(srcType); + @SuppressWarnings("unchecked") // registration requires that subtype extends T + TypeAdapter delegate = (TypeAdapter) subtypeToDelegate.get(srcType); + if (delegate == null) { + throw new JsonParseException("cannot serialize " + srcType.getName() + + "; did you forget to register a subtype?"); + } + JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject(); + + if (maintainType) { + Streams.write(jsonObject, out); + return; + } + + JsonObject clone = new JsonObject(); + + if (jsonObject.has(typeFieldName)) { + throw new JsonParseException("cannot serialize " + srcType.getName() + + " because it already defines a field named " + typeFieldName); + } + clone.add(typeFieldName, new JsonPrimitive(label)); + + for (Map.Entry e : jsonObject.entrySet()) { + clone.add(e.getKey(), e.getValue()); + } + Streams.write(clone, out); + } + }.nullSafe(); + } +} From 904046b0671898beb5504b66b68dc18dad3d2083 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Mon, 4 Mar 2019 21:39:47 +0200 Subject: [PATCH 250/496] Update README.md --- core-java-8/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-8/README.md b/core-java-8/README.md index 540a5f677f..eca07883e0 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -39,3 +39,4 @@ - [Java @Deprecated Annotation](https://www.baeldung.com/java-deprecated) - [Java 8 Predicate Chain](https://www.baeldung.com/java-predicate-chain) - [Method References in Java](https://www.baeldung.com/java-method-references) +- [Creating a Custom Annotation in Java](https://www.baeldung.com/java-custom-annotation) From 3186e484037e39ce9fa61874ce911f8a9dd90156 Mon Sep 17 00:00:00 2001 From: Rodolfo Felipe Date: Mon, 4 Mar 2019 20:43:14 -0400 Subject: [PATCH 251/496] BAEL-2448-Rev1 Changing examples to unit tests instead of plain methods after advice from editor. --- .../CollectionFilteringExamples.java | 51 ------------- .../filtering/CollectionFilteringTest.java | 73 +++++++++++++++++++ 2 files changed, 73 insertions(+), 51 deletions(-) delete mode 100644 core-java-collections-list/src/main/java/com/baeldung/collection/filtering/CollectionFilteringExamples.java create mode 100644 core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java diff --git a/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/CollectionFilteringExamples.java b/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/CollectionFilteringExamples.java deleted file mode 100644 index a7ab5840f7..0000000000 --- a/core-java-collections-list/src/main/java/com/baeldung/collection/filtering/CollectionFilteringExamples.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.collection.filtering; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Various filtering examples. - * - * @author Rodolfo Felipe - */ -public class CollectionFilteringExamples { - - private List buildEmployeeList() { - return Arrays.asList(new Employee(1, "Mike", 1), new Employee(2, "John", 1), new Employee(3, "Mary", 1), new Employee(4, "Joe", 2), new Employee(5, "Nicole", 2), new Employee(6, "Alice", 2), new Employee(7, "Bob", 3), new Employee(8, "Scarlett", 3)); - } - - private List employeeNameFilter() { - return Arrays.asList("Alice", "Mike", "Bob"); - } - - private List getFilteredEmployeeList() { - List filteredList = new ArrayList<>(); - for (Employee employee : buildEmployeeList()) { - for (String name : employeeNameFilter()) { - if (employee.getName() - .equalsIgnoreCase(name)) { - filteredList.add(employee); - } - } - } - return filteredList; - } - - private List getFilteredEmployeeListLambdaExample() { - return buildEmployeeList().stream() - .filter(employee -> employeeNameFilter().contains(employee.getName())) - .collect(Collectors.toList()); - } - - private List getFilteredEmployeeListLambdaExampleWithHashSetContains() { - Set nameFilterSet = employeeNameFilter().stream() - .collect(Collectors.toSet()); - return buildEmployeeList().stream() - .filter(employee -> nameFilterSet.contains(employee.getName())) - .collect(Collectors.toList()); - } - -} diff --git a/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java b/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java new file mode 100644 index 0000000000..bf3ec53abb --- /dev/null +++ b/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java @@ -0,0 +1,73 @@ +package com.baeldung.collection.filtering; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; + +/** + * Various filtering examples. + * + * @author Rodolfo Felipe + */ +public class CollectionFilteringTest { + + private List buildEmployeeList() { + return Arrays.asList(new Employee(1, "Mike", 1), new Employee(2, "John", 1), new Employee(3, "Mary", 1), new Employee(4, "Joe", 2), new Employee(5, "Nicole", 2), new Employee(6, "Alice", 2), new Employee(7, "Bob", 3), new Employee(8, "Scarlett", 3)); + } + + private List employeeNameFilter() { + return Arrays.asList("Alice", "Mike", "Bob"); + } + + @Test + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingForEachLoop() { + List filteredList = new ArrayList<>(); + List originalList = buildEmployeeList(); + List nameFilter = employeeNameFilter(); + + for (Employee employee : originalList) { + for (String name : nameFilter) { + if (employee.getName() + .equalsIgnoreCase(name)) { + filteredList.add(employee); + } + } + } + + Assert.assertThat(filteredList.size(), Matchers.is(nameFilter.size())); + } + + @Test + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambda() { + List filteredList; + List originalList = buildEmployeeList(); + List nameFilter = employeeNameFilter(); + + filteredList = originalList.stream() + .filter(employee -> nameFilter.contains(employee.getName())) + .collect(Collectors.toList()); + + Assert.assertThat(filteredList.size(), Matchers.is(nameFilter.size())); + } + + @Test + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaAndHashSet() { + List filteredList; + List originalList = buildEmployeeList(); + Set nameFilterSet = employeeNameFilter().stream() + .collect(Collectors.toSet()); + + filteredList = originalList.stream() + .filter(employee -> nameFilterSet.contains(employee.getName())) + .collect(Collectors.toList()); + + Assert.assertThat(filteredList.size(), Matchers.is(nameFilterSet.size())); + } + +} From bf31484ee367db29fc23a190698da2207ce6d0de Mon Sep 17 00:00:00 2001 From: Rodolfo Felipe Date: Mon, 4 Mar 2019 20:49:30 -0400 Subject: [PATCH 252/496] BAEL-2448-Rev2 Changing method names to comply with Jenkins PMD method naming rules. --- .../collection/filtering/CollectionFilteringTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java b/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java index bf3ec53abb..3b4a087ecd 100644 --- a/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java +++ b/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java @@ -26,7 +26,7 @@ public class CollectionFilteringTest { } @Test - public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingForEachLoop() { + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingForEachLoopUnitTest() { List filteredList = new ArrayList<>(); List originalList = buildEmployeeList(); List nameFilter = employeeNameFilter(); @@ -44,7 +44,7 @@ public class CollectionFilteringTest { } @Test - public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambda() { + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaUnitTest() { List filteredList; List originalList = buildEmployeeList(); List nameFilter = employeeNameFilter(); @@ -57,7 +57,7 @@ public class CollectionFilteringTest { } @Test - public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaAndHashSet() { + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaAndHashSetUnitTest() { List filteredList; List originalList = buildEmployeeList(); Set nameFilterSet = employeeNameFilter().stream() From 245e0f32b33ed5c3465bead17bbf87a8cb49d8a2 Mon Sep 17 00:00:00 2001 From: Rodolfo Felipe Date: Mon, 4 Mar 2019 20:54:50 -0400 Subject: [PATCH 253/496] BAEL-2448-Rev3 Renaming test class so it passes PMD checks. Reverting method names to previous commit. --- ...ilteringTest.java => CollectionFilteringUnitTest.java} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename core-java-collections-list/src/test/java/com/baeldung/collection/filtering/{CollectionFilteringTest.java => CollectionFilteringUnitTest.java} (92%) diff --git a/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java b/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java similarity index 92% rename from core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java rename to core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java index 3b4a087ecd..cbc7136192 100644 --- a/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringTest.java +++ b/core-java-collections-list/src/test/java/com/baeldung/collection/filtering/CollectionFilteringUnitTest.java @@ -15,7 +15,7 @@ import org.junit.Test; * * @author Rodolfo Felipe */ -public class CollectionFilteringTest { +public class CollectionFilteringUnitTest { private List buildEmployeeList() { return Arrays.asList(new Employee(1, "Mike", 1), new Employee(2, "John", 1), new Employee(3, "Mary", 1), new Employee(4, "Joe", 2), new Employee(5, "Nicole", 2), new Employee(6, "Alice", 2), new Employee(7, "Bob", 3), new Employee(8, "Scarlett", 3)); @@ -26,7 +26,7 @@ public class CollectionFilteringTest { } @Test - public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingForEachLoopUnitTest() { + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingForEachLoop() { List filteredList = new ArrayList<>(); List originalList = buildEmployeeList(); List nameFilter = employeeNameFilter(); @@ -44,7 +44,7 @@ public class CollectionFilteringTest { } @Test - public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaUnitTest() { + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambda() { List filteredList; List originalList = buildEmployeeList(); List nameFilter = employeeNameFilter(); @@ -57,7 +57,7 @@ public class CollectionFilteringTest { } @Test - public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaAndHashSetUnitTest() { + public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaAndHashSet() { List filteredList; List originalList = buildEmployeeList(); Set nameFilterSet = employeeNameFilter().stream() From b095add969b84a4f72d6b4864ec938407ac8f07f Mon Sep 17 00:00:00 2001 From: Josephine Barboza Date: Tue, 5 Mar 2019 22:00:33 +0530 Subject: [PATCH 254/496] BAEL-2725 --- .../groovy/com/baeldung/lists/ListTest.groovy | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy index 89a0194742..f682503ed4 100644 --- a/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy @@ -20,11 +20,11 @@ class ListTest{ ArrayList arrList = [1, 2, 3] assertTrue(arrList.class == ArrayList) - def list2 = new ArrayList(arrList) - assertTrue(list2 == arrList) + def copyList = new ArrayList(arrList) + assertTrue(copyList == arrList) - def list3 = arrList.clone() - assertTrue(list3 == arrList) + def cloneList = arrList.clone() + assertTrue(cloneList == arrList) } @Test @@ -122,30 +122,33 @@ class ListTest{ @Test void testFilteringOnLists(){ - def list = [2, 1, 3, 4, 5, 6, 76] + def filterList = [2, 1, 3, 4, 5, 6, 76] - assertTrue(list.find{it > 3} == 4) + assertTrue(filterList.find{it > 3} == 4) - assertTrue(list.findAll{it > 3} == [4, 5, 6, 76]) + assertTrue(filterList.findAll{it > 3} == [4, 5, 6, 76]) - assertTrue(list.findAll{ it instanceof Number} == [2, 1, 3, 4, 5, 6, 76]) + assertTrue(filterList.findAll{ it instanceof Number} == [2, 1, 3, 4, 5, 6, 76]) + + assertTrue(filterList.grep( Number )== [2, 1, 3, 4, 5, 6, 76]) + + assertTrue(filterList.grep{ it> 6 }== [76]) - assertFalse(list.every{ it < 6}) + def conditionList = [2, 1, 3, 4, 5, 6, 76] + + assertFalse(conditionList.every{ it < 6}) - assertTrue(list.any{ it%2 == 0}) + assertTrue(conditionList.any{ it%2 == 0}) - assertTrue(list.grep( Number )== [2, 1, 3, 4, 5, 6, 76]) - - assertTrue(list.grep{ it> 6 }== [76]) } @Test void testGetUniqueItemsInAList(){ assertTrue([1, 3, 3, 4].toUnique() == [1, 3, 4]) - def list = [1, 3, 3, 4] - list.unique() - assertTrue(list == [1, 3, 4]) + def uniqueList = [1, 3, 3, 4] + uniqueList.unique() + assertTrue(uniqueList == [1, 3, 4]) assertTrue(["A", "B", "Ba", "Bat", "Cat"].toUnique{ it.size()} == ["A", "Ba", "Bat"]) } @@ -160,11 +163,11 @@ class ListTest{ list.sort(mc) assertTrue(list == [2, 1, 1, 0]) - def list1 = ["na", "ppp", "as"] - assertTrue(list1.max() == "ppp") + def strList = ["na", "ppp", "as"] + assertTrue(strList.max() == "ppp") Comparator minc = {a,b -> a == b? 0: a < b? -1 : 1} - def list2 = [3, 2, 0, 7] - assertTrue(list2.min(minc) == 0) + def numberList = [3, 2, 0, 7] + assertTrue(numberList.min(minc) == 0) } } \ No newline at end of file From 9c62f1ea0c0be4a6a352a76496448ba9e422d149 Mon Sep 17 00:00:00 2001 From: Ganesh Pagade Date: Tue, 5 Mar 2019 22:27:46 +0530 Subject: [PATCH 255/496] minor change --- .../java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java b/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java index 7032dde1ce..020118aa2b 100644 --- a/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java +++ b/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java @@ -37,8 +37,7 @@ public class GsonAdvanceUnitTest { Gson gson = new Gson(); List list = gson.fromJson(inputString, ArrayList.class); - assertEquals(2, list.size()); - int id = list.get(0).getId(); + assertEquals(1, list.get(0).getId()); } @Test public void givenJsonString_whenDeserializing_thenReturnListOfMyClass() { From b1834b6d96b566faed1f520552cbb14e650052d6 Mon Sep 17 00:00:00 2001 From: Ganesh Pagade Date: Tue, 5 Mar 2019 22:29:31 +0530 Subject: [PATCH 256/496] minor change --- .../main/java/org/baeldung/gson/entities/MyClass.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/gson/src/main/java/org/baeldung/gson/entities/MyClass.java b/gson/src/main/java/org/baeldung/gson/entities/MyClass.java index 86e14985da..827ca10cb0 100644 --- a/gson/src/main/java/org/baeldung/gson/entities/MyClass.java +++ b/gson/src/main/java/org/baeldung/gson/entities/MyClass.java @@ -9,16 +9,6 @@ public class MyClass { strings = new String[] { "a", "b" }; } - - // @Override - // public String toString() { - // return "{" + - // "id=" + id + - // ", name='" + name + '\'' + - // ", strings=" + Arrays.toString(strings) + - // '}'; - // } - public int getId() { return id; } From 0983aa916328e8097908b0fc6eb2f462bbef7e85 Mon Sep 17 00:00:00 2001 From: eelhazati Date: Tue, 5 Mar 2019 21:14:51 +0100 Subject: [PATCH 257/496] CF UAA config && demo. --- cloud-foundry-uaa/cf-uaa-config/uaa.yml | 73 +++++++++++++++++ .../cf-uaa-oauth2-client/pom.xml | 43 ++++++++++ .../client/CFUAAOAuth2ClientApplication.java | 13 +++ .../client/CFUAAOAuth2ClientController.java | 80 +++++++++++++++++++ .../src/main/resources/application.properties | 23 ++++++ .../src/main/resources/templates/index.html | 1 + .../cf-uaa-oauth2-resource-server/pom.xml | 43 ++++++++++ .../CFUAAOAuth2ResourceServerApplication.java | 13 +++ ...UAAOAuth2ResourceServerRestController.java | 28 +++++++ ...h2ResourceServerSecurityConfiguration.java | 21 +++++ .../src/main/resources/application.properties | 16 ++++ 11 files changed, 354 insertions(+) create mode 100644 cloud-foundry-uaa/cf-uaa-config/uaa.yml create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientApplication.java create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientController.java create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/templates/index.html create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerApplication.java create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerRestController.java create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java create mode 100644 cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties diff --git a/cloud-foundry-uaa/cf-uaa-config/uaa.yml b/cloud-foundry-uaa/cf-uaa-config/uaa.yml new file mode 100644 index 0000000000..b782c2b681 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-config/uaa.yml @@ -0,0 +1,73 @@ +issuer: + uri: http://localhost:8080/uaa + +spring_profiles: postgresql,default + +database.driverClassName: org.postgresql.Driver +database.url: jdbc:postgresql:uaadb2 +database.username: postgres +database.password: postgres + +encryption: + active_key_label: CHANGE-THIS-KEY + encryption_keys: + - label: CHANGE-THIS-KEY + passphrase: CHANGEME + +login: + serviceProviderKey: | + -----BEGIN RSA PRIVATE KEY----- + MIICXQIBAAKBgQDHtC5gUXxBKpEqZTLkNvFwNGnNIkggNOwOQVNbpO0WVHIivig5 + L39WqS9u0hnA+O7MCA/KlrAR4bXaeVVhwfUPYBKIpaaTWFQR5cTR1UFZJL/OF9vA + fpOwznoD66DDCnQVpbCjtDYWX+x6imxn8HCYxhMol6ZnTbSsFW6VZjFMjQIDAQAB + AoGAVOj2Yvuigi6wJD99AO2fgF64sYCm/BKkX3dFEw0vxTPIh58kiRP554Xt5ges + 7ZCqL9QpqrChUikO4kJ+nB8Uq2AvaZHbpCEUmbip06IlgdA440o0r0CPo1mgNxGu + lhiWRN43Lruzfh9qKPhleg2dvyFGQxy5Gk6KW/t8IS4x4r0CQQD/dceBA+Ndj3Xp + ubHfxqNz4GTOxndc/AXAowPGpge2zpgIc7f50t8OHhG6XhsfJ0wyQEEvodDhZPYX + kKBnXNHzAkEAyCA76vAwuxqAd3MObhiebniAU3SnPf2u4fdL1EOm92dyFs1JxyyL + gu/DsjPjx6tRtn4YAalxCzmAMXFSb1qHfwJBAM3qx3z0gGKbUEWtPHcP7BNsrnWK + vw6By7VC8bk/ffpaP2yYspS66Le9fzbFwoDzMVVUO/dELVZyBnhqSRHoXQcCQQCe + A2WL8S5o7Vn19rC0GVgu3ZJlUrwiZEVLQdlrticFPXaFrn3Md82ICww3jmURaKHS + N+l4lnMda79eSp3OMmq9AkA0p79BvYsLshUJJnvbk76pCjR28PK4dV1gSDUEqQMB + qy45ptdwJLqLJCeNoR0JUcDNIRhOCuOPND7pcMtX6hI/ + -----END RSA PRIVATE KEY----- + serviceProviderKeyPassword: password + serviceProviderCertificate: | + -----BEGIN CERTIFICATE----- + MIIDSTCCArKgAwIBAgIBADANBgkqhkiG9w0BAQQFADB8MQswCQYDVQQGEwJhdzEO + MAwGA1UECBMFYXJ1YmExDjAMBgNVBAoTBWFydWJhMQ4wDAYDVQQHEwVhcnViYTEO + MAwGA1UECxMFYXJ1YmExDjAMBgNVBAMTBWFydWJhMR0wGwYJKoZIhvcNAQkBFg5h + cnViYUBhcnViYS5hcjAeFw0xNTExMjAyMjI2MjdaFw0xNjExMTkyMjI2MjdaMHwx + CzAJBgNVBAYTAmF3MQ4wDAYDVQQIEwVhcnViYTEOMAwGA1UEChMFYXJ1YmExDjAM + BgNVBAcTBWFydWJhMQ4wDAYDVQQLEwVhcnViYTEOMAwGA1UEAxMFYXJ1YmExHTAb + BgkqhkiG9w0BCQEWDmFydWJhQGFydWJhLmFyMIGfMA0GCSqGSIb3DQEBAQUAA4GN + ADCBiQKBgQDHtC5gUXxBKpEqZTLkNvFwNGnNIkggNOwOQVNbpO0WVHIivig5L39W + qS9u0hnA+O7MCA/KlrAR4bXaeVVhwfUPYBKIpaaTWFQR5cTR1UFZJL/OF9vAfpOw + znoD66DDCnQVpbCjtDYWX+x6imxn8HCYxhMol6ZnTbSsFW6VZjFMjQIDAQABo4Ha + MIHXMB0GA1UdDgQWBBTx0lDzjH/iOBnOSQaSEWQLx1syGDCBpwYDVR0jBIGfMIGc + gBTx0lDzjH/iOBnOSQaSEWQLx1syGKGBgKR+MHwxCzAJBgNVBAYTAmF3MQ4wDAYD + VQQIEwVhcnViYTEOMAwGA1UEChMFYXJ1YmExDjAMBgNVBAcTBWFydWJhMQ4wDAYD + VQQLEwVhcnViYTEOMAwGA1UEAxMFYXJ1YmExHTAbBgkqhkiG9w0BCQEWDmFydWJh + QGFydWJhLmFyggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAYvBJ + 0HOZbbHClXmGUjGs+GS+xC1FO/am2suCSYqNB9dyMXfOWiJ1+TLJk+o/YZt8vuxC + KdcZYgl4l/L6PxJ982SRhc83ZW2dkAZI4M0/Ud3oePe84k8jm3A7EvH5wi5hvCkK + RpuRBwn3Ei+jCRouxTbzKPsuCVB+1sNyxMTXzf0= + -----END CERTIFICATE----- + +#The secret that an external login server will use to authenticate to the uaa using the id `login` +LOGIN_SECRET: loginsecret + +jwt: + token: + signing-key: | + -----BEGIN RSA PRIVATE KEY----- + MIIEpAIBAAKCAQEAqUeygEfDGxI6c1VDQ6xIyUSLrP6iz1y97iHFbtXSxXaArL4a + ... + v6Mtt5LcRAAVP7pemunTdju4h8Q/noKYlVDVL30uLYUfKBL4UKfOBw== + -----END RSA PRIVATE KEY----- + verification-key: | + -----BEGIN PUBLIC KEY----- + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqUeygEfDGxI6c1VDQ6xI + ... + AwIDAQAB + -----END PUBLIC KEY----- diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml b/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml new file mode 100644 index 0000000000..8e31cc41fb --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + com.example + cf-uaa-oauth2-client + 0.0.1-SNAPSHOT + uaa-client-webapp + Demo project for Spring Boot + + + 1.8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-oauth2-client + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientApplication.java b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientApplication.java new file mode 100644 index 0000000000..c9e81fcd5d --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.cfuaa.oauth2.client; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CFUAAOAuth2ClientApplication { + + public static void main(String[] args) { + SpringApplication.run(CFUAAOAuth2ClientApplication.class, args); + } + +} diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientController.java b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientController.java new file mode 100644 index 0000000000..b1631ed327 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/java/com/baeldung/cfuaa/oauth2/client/CFUAAOAuth2ClientController.java @@ -0,0 +1,80 @@ +package com.baeldung.cfuaa.oauth2.client; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +@RestController +public class CFUAAOAuth2ClientController { + + @Value("${resource.server.url}") + private String remoteResourceServer; + + private RestTemplate restTemplate; + + private OAuth2AuthorizedClientService authorizedClientService; + + public CFUAAOAuth2ClientController(OAuth2AuthorizedClientService authorizedClientService) { + this.authorizedClientService = authorizedClientService; + this.restTemplate = new RestTemplate(); + } + + @RequestMapping("/") + public String index(OAuth2AuthenticationToken authenticationToken) { + OAuth2AuthorizedClient oAuth2AuthorizedClient = this.authorizedClientService.loadAuthorizedClient(authenticationToken.getAuthorizedClientRegistrationId(), authenticationToken.getName()); + OAuth2AccessToken oAuth2AccessToken = oAuth2AuthorizedClient.getAccessToken(); + + String response = "Hello, " + authenticationToken.getPrincipal().getName(); + response += "

"; + response += "Here is your accees token :
" + oAuth2AccessToken.getTokenValue(); + response += "
"; + response += "
You can use it to call these Resource Server APIs:"; + response += "

"; + response += "Call Resource Server Read API"; + response += "
"; + response += "Call Resource Server Write API"; + return response; + } + + @RequestMapping("/read") + public String read(OAuth2AuthenticationToken authenticationToken) { + String url = remoteResourceServer + "/read"; + return callResourceServer(authenticationToken, url); + } + + @RequestMapping("/write") + public String write(OAuth2AuthenticationToken authenticationToken) { + String url = remoteResourceServer + "/write"; + return callResourceServer(authenticationToken, url); + } + + private String callResourceServer(OAuth2AuthenticationToken authenticationToken, String url) { + OAuth2AuthorizedClient oAuth2AuthorizedClient = this.authorizedClientService.loadAuthorizedClient(authenticationToken.getAuthorizedClientRegistrationId(), authenticationToken.getName()); + OAuth2AccessToken oAuth2AccessToken = oAuth2AuthorizedClient.getAccessToken(); + + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", "Bearer " + oAuth2AccessToken.getTokenValue()); + + HttpEntity entity = new HttpEntity<>("parameters", headers); + ResponseEntity responseEntity = null; + + String response = null; + try { + responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); + response = responseEntity.getBody(); + } catch (HttpClientErrorException e) { + response = e.getMessage(); + } + return response; + } +} \ No newline at end of file diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties new file mode 100644 index 0000000000..de8e1a7b9f --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties @@ -0,0 +1,23 @@ +# SECURITY OAUTH2 CLIENT (OAuth2ClientProperties) +#spring.security.oauth2.client.provider.*= # OAuth provider details. +#spring.security.oauth2.client.registration.*= # OAuth client registrations. + +server.port=8081 +#server.servlet.context-path=/uaa-client-webapp + +uaa.url=http://localhost:8080/uaa +resource.server.url=http://localhost:8082 + +spring.security.oauth2.client.registration.uaa.client-name=UAA OAuth2 Client +spring.security.oauth2.client.registration.uaa.client-id=client1 +spring.security.oauth2.client.registration.uaa.client-secret=client1 +spring.security.oauth2.client.registration.uaa.authorization-grant-type=authorization_code +spring.security.oauth2.client.registration.uaa.scope=resource.read,resource.write,openid,profile +spring.security.oauth2.client.registration.uaa.redirect-uri=http://localhost:8081/login/oauth2/code/uaa +#spring.security.oauth2.client.registration.uaa.redirect-uri=http://localhost:8081/** + +spring.security.oauth2.client.provider.uaa.token-uri=${uaa.url}/oauth/token +spring.security.oauth2.client.provider.uaa.authorization-uri=${uaa.url}/oauth/authorize +spring.security.oauth2.client.provider.uaa.jwk-set-uri=${uaa.url}/token_keys +spring.security.oauth2.client.provider.uaa.user-info-uri=${uaa.url}/userinfo +spring.security.oauth2.client.provider.uaa.user-name-attribute=user_name diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/templates/index.html b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/templates/index.html new file mode 100644 index 0000000000..eb6e267b94 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/templates/index.html @@ -0,0 +1 @@ +tintin \ No newline at end of file diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml new file mode 100644 index 0000000000..9cf8993cd2 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + com.baeldung.cfuaa + cf-uaa-oauth2-resource-server + 0.0.1-SNAPSHOT + cf-uaa-oauth2-resource-server + Demo project for Spring Boot + + + 1.8 + + + + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + org.springframework.boot + spring-boot-starter-web + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerApplication.java b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerApplication.java new file mode 100644 index 0000000000..51ad6e938d --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.cfuaa.oauth2.resourceserver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CFUAAOAuth2ResourceServerApplication { + + public static void main(String[] args) { + SpringApplication.run(CFUAAOAuth2ResourceServerApplication.class, args); + } + +} diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerRestController.java b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerRestController.java new file mode 100644 index 0000000000..c08f17d8d8 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerRestController.java @@ -0,0 +1,28 @@ +package com.baeldung.cfuaa.oauth2.resourceserver; + +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Principal; + +@RestController +public class CFUAAOAuth2ResourceServerRestController { + + @GetMapping("/") + public String index(@AuthenticationPrincipal Jwt jwt) { + return String.format("Hello, %s!", jwt.getSubject()); + } + + @GetMapping("/read") + public String read(JwtAuthenticationToken jwtAuthenticationToken) { + return "Hello write: " + jwtAuthenticationToken.getTokenAttributes(); + } + + @GetMapping("/write") + public String write(Principal principal) { + return "Hello write: " + principal.getName(); + } +} diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java new file mode 100644 index 0000000000..d04d51cda3 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/java/com/baeldung/cfuaa/oauth2/resourceserver/CFUAAOAuth2ResourceServerSecurityConfiguration.java @@ -0,0 +1,21 @@ +package com.baeldung.cfuaa.oauth2.resourceserver; + +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@EnableWebSecurity +public class CFUAAOAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .antMatchers("/read/**").hasAuthority("SCOPE_resource.read") + .antMatchers("/write/**").hasAuthority("SCOPE_resource.write") + .anyRequest().authenticated() + .and() + .oauth2ResourceServer() + .jwt(); + } +} \ No newline at end of file diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties new file mode 100644 index 0000000000..ba9b95e0d4 --- /dev/null +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties @@ -0,0 +1,16 @@ +server.port=8082 + +uaa.url=http://localhost:8080/uaa + +#approch1 +spring.security.oauth2.resourceserver.jwt.issuer-uri=${uaa.url}/oauth/token + +#approch2 +#spring.security.oauth2.resourceserver.jwt.jwk-set-uri=${uaa.url}/token_key + +# SECURITY OAUTH2 CLIENT (OAuth2ClientProperties) +#security.oauth2.client.client-id=client1 +#security.oauth2.client.client-secret=client1 + +#security.oauth2.resource.jwt.key-uri=${uaa.url}/token_key +#security.oauth2.resource.token-info-uri=${uaa.url}/oauth/check_token From 9f22567d4f0935ac1c4da08c8f745847a3f477a4 Mon Sep 17 00:00:00 2001 From: amdegregorio Date: Sat, 2 Mar 2019 11:06:35 -0500 Subject: [PATCH 258/496] BAEL-2727 Example Code --- .../main/groovy/com/baeldung/io/Task.groovy | 8 ++ .../src/main/resources/binaryExample.jpg | Bin 0 -> 1139 bytes core-groovy/src/main/resources/ioData.txt | Bin 0 -> 34 bytes core-groovy/src/main/resources/ioInput.txt | 4 + core-groovy/src/main/resources/ioOutput.txt | 3 + .../src/main/resources/ioSerializedObject.txt | Bin 0 -> 199 bytes .../baeldung/io/DataAndObjectsUnitTest.groovy | 51 +++++++ .../baeldung/io/ReadExampleUnitTest.groovy | 134 ++++++++++++++++++ .../io/TraverseFileTreeUnitTest.groovy | 61 ++++++++ .../baeldung/io/WriteExampleUnitTest.groovy | 96 +++++++++++++ 10 files changed, 357 insertions(+) create mode 100644 core-groovy/src/main/groovy/com/baeldung/io/Task.groovy create mode 100644 core-groovy/src/main/resources/binaryExample.jpg create mode 100644 core-groovy/src/main/resources/ioData.txt create mode 100644 core-groovy/src/main/resources/ioInput.txt create mode 100644 core-groovy/src/main/resources/ioOutput.txt create mode 100644 core-groovy/src/main/resources/ioSerializedObject.txt create mode 100644 core-groovy/src/test/groovy/com/baeldung/io/DataAndObjectsUnitTest.groovy create mode 100644 core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy create mode 100644 core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy create mode 100644 core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy diff --git a/core-groovy/src/main/groovy/com/baeldung/io/Task.groovy b/core-groovy/src/main/groovy/com/baeldung/io/Task.groovy new file mode 100644 index 0000000000..8a3bedc048 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/io/Task.groovy @@ -0,0 +1,8 @@ +package com.baeldung.io + +class Task implements Serializable { + String description + Date startDate + Date dueDate + int status +} diff --git a/core-groovy/src/main/resources/binaryExample.jpg b/core-groovy/src/main/resources/binaryExample.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4b32645ac9b8030b3ed570263cd4f5c477a13d0f GIT binary patch literal 1139 zcmex=``2_j6xdp@o1cgOJMMZh|#U;coyG6VInuyV4pa*FVB^NNrR z{vTivwh= zDOELf4NWZ*Q!{f5ODks=S2uSLPp{yR(6I1`$f)F$)U@=B%&g*)(z5c3%Btp;*0%PJ z&aO$5r%atTea6gLixw|gx@`H1m8&*w-m-Pu_8mKS9XfpE=&|D`PM*4S`O4L6*Kgds z_3+W-Cr_U}fAR9w$4{TXeEs(Q$Io9Ne=#yJL%ap|8JfQYf&OA*VPR%r2lxYE z#}NLy#lXYN2#h>tK?Zwsdx80d=DeqoLp33BN>@lV5)W0p*xBF6khQ3U6 zd|u@KEmAIb41aHDTx{>#nkC<~Jx*3U>Uf9g?-TCdWVB0j6ID+27Ax=^&QO1*obaGL zF@Af(VsHJEk9BnJsHWWR@(aq%*y``S^~J;|=RU8_)Ly*5{gHTgeOkOMcddR{_HHJz zvQ1OwD?L;4=b8C4y2+f+eZ9r{3-#^)Y%cv%t}yrfs5Vpmm)v58sevc%N~g5DeGlVV zen;w0{g3vKPVbM$DeSnqzRcwulRHm+nTf1O)!$mr^-KOSRoFk$+xua*)BcNgS4?)c zJmZ~x;J`eG!p2v;m3tgpmiHXGxVCFba%`lR*R7Y=?$$r(Ynh{RrL^;1{5J77O?5WM z**o@_7PHNN%&k!~X*$aq^NUPgiw)$pd*-g~k$LbSVf`^V{tx~~);Hxo;?{AXX;%T4=@?p*vK{+sQO z^N*QpZr%B@-hbzZ^0v^!G2S)%V(+Z7S`#pThVb9#419YYi~gGYu%0(_AMb~Ea~Hn& swmNlL<_F!qdpIu&y0KsRHShT>jde1|Wuqm7uEupQ40*6 + out.writeUTF(message) + out.writeInt(length) + out.writeBoolean(valid) + } + + String loadedMessage = "" + int loadedLength + boolean loadedValid + + new File('src/main/resources/ioData.txt').withDataInputStream { is -> + loadedMessage = is.readUTF() + loadedLength = is.readInt() + loadedValid = is.readBoolean() + } + + assertEquals(message, loadedMessage) + assertEquals(length, loadedLength) + assertEquals(valid, loadedValid) + } + + @Test + void whenUsingWithObjectOutputStream_thenObjectIsSerializedToFile() { + Task task = new Task(description:'Take out the trash', startDate:new Date(), status:0) + new File('src/main/resources/ioSerializedObject.txt').withObjectOutputStream { out -> + out.writeObject(task) + } + + Task taskRead + + new File('src/main/resources/ioSerializedObject.txt').withObjectInputStream { is -> + taskRead = is.readObject() + } + + assertEquals(task.description, taskRead.description) + assertEquals(task.startDate, taskRead.startDate) + assertEquals(task.status, taskRead.status) + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy new file mode 100644 index 0000000000..bed77b4d81 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/io/ReadExampleUnitTest.groovy @@ -0,0 +1,134 @@ +package com.baeldung.io + +import static org.junit.Assert.* +import org.junit.Test + +class ReadExampleUnitTest { + + @Test + void whenUsingEachLine_thenCorrectLinesReturned() { + def expectedList = [ + 'First line of text', + 'Second line of text', + 'Third line of text', + 'Fourth line of text'] + + def lines = [] + + new File('src/main/resources/ioInput.txt').eachLine { line -> + lines.add(line) + } + assertEquals(expectedList, lines) + } + + @Test + void whenUsingReadEachLineWithLineNumber_thenCorrectLinesReturned() { + def expectedList = [ + 'Second line of text', + 'Third line of text', + 'Fourth line of text'] + + def lineNoRange = 2..4 + def lines = [] + + new File('src/main/resources/ioInput.txt').eachLine { line, lineNo -> + if (lineNoRange.contains(lineNo)) { + lines.add(line) + } + } + assertEquals(expectedList, lines) + } + + @Test + void whenUsingReadEachLineWithLineNumberStartAtZero_thenCorrectLinesReturned() { + def expectedList = [ + 'Second line of text', + 'Third line of text', + 'Fourth line of text'] + + def lineNoRange = 1..3 + def lines = [] + + new File('src/main/resources/ioInput.txt').eachLine(0, { line, lineNo -> + if (lineNoRange.contains(lineNo)) { + lines.add(line) + } + }) + assertEquals(expectedList, lines) + } + + @Test + void whenUsingWithReader_thenLineCountReturned() { + def expectedCount = 4 + def actualCount = 0 + new File('src/main/resources/ioInput.txt').withReader { reader -> + while(reader.readLine()) { + actualCount++ + } + } + assertEquals(expectedCount, actualCount) + } + + @Test + void whenUsingNewReader_thenOutputFileCreated() { + def outputPath = 'src/main/resources/ioOut.txt' + def reader = new File('src/main/resources/ioInput.txt').newReader() + new File(outputPath).append(reader) + reader.close() + def ioOut = new File(outputPath) + assertTrue(ioOut.exists()) + ioOut.delete() + } + + @Test + void whenUsingWithInputStream_thenCorrectBytesAreReturned() { + def expectedLength = 1139 + byte[] data = [] + new File("src/main/resources/binaryExample.jpg").withInputStream { stream -> + data = stream.getBytes() + } + assertEquals(expectedLength, data.length) + } + + @Test + void whenUsingNewInputStream_thenOutputFileCreated() { + def outputPath = 'src/main/resources/binaryOut.jpg' + def is = new File('src/main/resources/binaryExample.jpg').newInputStream() + new File(outputPath).append(is) + is.close() + def ioOut = new File(outputPath) + assertTrue(ioOut.exists()) + ioOut.delete() + } + + @Test + void whenUsingCollect_thenCorrectListIsReturned() { + def expectedList = ['First line of text', 'Second line of text', 'Third line of text', 'Fourth line of text'] + + def actualList = new File('src/main/resources/ioInput.txt').collect {it} + assertEquals(expectedList, actualList) + } + + @Test + void whenUsingAsStringArray_thenCorrectArrayIsReturned() { + String[] expectedArray = ['First line of text', 'Second line of text', 'Third line of text', 'Fourth line of text'] + + def actualArray = new File('src/main/resources/ioInput.txt') as String[] + assertArrayEquals(expectedArray, actualArray) + } + + @Test + void whenUsingText_thenCorrectStringIsReturned() { + def ln = System.getProperty('line.separator') + def expectedString = "First line of text${ln}Second line of text${ln}Third line of text${ln}Fourth line of text" + def actualString = new File('src/main/resources/ioInput.txt').text + assertEquals(expectedString.toString(), actualString) + } + + @Test + void whenUsingBytes_thenByteArrayIsReturned() { + def expectedLength = 1139 + def contents = new File('src/main/resources/binaryExample.jpg').bytes + assertEquals(expectedLength, contents.length) + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy new file mode 100644 index 0000000000..dac0189fb9 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/io/TraverseFileTreeUnitTest.groovy @@ -0,0 +1,61 @@ +package com.baeldung.io + +import org.junit.Test + +import groovy.io.FileType +import groovy.io.FileVisitResult + +class TraverseFileTreeUnitTest { + @Test + void whenUsingEachFile_filesAreListed() { + new File('src/main/resources').eachFile { file -> + println file.name + } + } + + @Test(expected = IllegalArgumentException) + void whenUsingEachFileOnAFile_anErrorOccurs() { + new File('src/main/resources/ioInput.txt').eachFile { file -> + println file.name + } + } + + @Test + void whenUsingEachFileMatch_filesAreListed() { + new File('src/main/resources').eachFileMatch(~/io.*\.txt/) { file -> + println file.name + } + } + + @Test + void whenUsingEachFileRecurse_thenFilesInSubfoldersAreListed() { + new File('src/main').eachFileRecurse(FileType.FILES) { file -> + println "$file.parent $file.name" + } + } + + @Test + void whenUsingEachFileRecurse_thenDirsInSubfoldersAreListed() { + new File('src/main').eachFileRecurse(FileType.DIRECTORIES) { file -> + println "$file.parent $file.name" + } + } + + @Test + void whenUsingEachDirRecurse_thenDirsAndSubDirsAreListed() { + new File('src/main').eachDirRecurse { dir -> + println "$dir.parent $dir.name" + } + } + + @Test + void whenUsingTraverse_thenDirectoryIsTraversed() { + new File('src/main').traverse { file -> + if (file.directory && file.name == 'groovy') { + FileVisitResult.SKIP_SUBTREE + } else { + println "$file.parent - $file.name" + } + } + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy new file mode 100644 index 0000000000..81758b430a --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/io/WriteExampleUnitTest.groovy @@ -0,0 +1,96 @@ +package com.baeldung.io + +import static org.junit.Assert.* + +import org.junit.Before +import org.junit.Test + +class WriteExampleUnitTest { + @Before + void clearOutputFile() { + new File('src/main/resources/ioOutput.txt').text = '' + new File('src/main/resources/ioBinaryOutput.bin').delete() + } + + @Test + void whenUsingWithWriter_thenFileCreated() { + def outputLines = [ + 'Line one of output example', + 'Line two of output example', + 'Line three of output example' + ] + + def outputFileName = 'src/main/resources/ioOutput.txt' + new File(outputFileName).withWriter { writer -> + outputLines.each { line -> + writer.writeLine line + } + } + def writtenLines = new File(outputFileName).collect {it} + assertEquals(outputLines, writtenLines) + } + + @Test + void whenUsingNewWriter_thenFileCreated() { + def outputLines = [ + 'Line one of output example', + 'Line two of output example', + 'Line three of output example' + ] + + def outputFileName = 'src/main/resources/ioOutput.txt' + def writer = new File(outputFileName).newWriter() + outputLines.forEach {line -> + writer.writeLine line + } + writer.flush() + writer.close() + + def writtenLines = new File(outputFileName).collect {it} + assertEquals(outputLines, writtenLines) + } + + @Test + void whenUsingDoubleLessThanOperator_thenFileCreated() { + def outputLines = [ + 'Line one of output example', + 'Line two of output example', + 'Line three of output example' + ] + + def ln = System.getProperty('line.separator') + def outputFileName = 'src/main/resources/ioOutput.txt' + new File(outputFileName) << "Line one of output example${ln}Line two of output example${ln}Line three of output example" + def writtenLines = new File(outputFileName).collect {it} + assertEquals(outputLines.size(), writtenLines.size()) + } + + @Test + void whenUsingBytes_thenBinaryFileCreated() { + def outputFileName = 'src/main/resources/ioBinaryOutput.bin' + def outputFile = new File(outputFileName) + byte[] outBytes = [44, 88, 22] + outputFile.bytes = outBytes + assertEquals(3, new File(outputFileName).size()) + } + + @Test + void whenUsingWithOutputStream_thenBinaryFileCreated() { + def outputFileName = 'src/main/resources/ioBinaryOutput.bin' + byte[] outBytes = [44, 88, 22] + new File(outputFileName).withOutputStream { stream -> + stream.write(outBytes) + } + assertEquals(3, new File(outputFileName).size()) + } + + @Test + void whenUsingNewOutputStream_thenBinaryFileCreated() { + def outputFileName = 'src/main/resources/ioBinaryOutput.bin' + byte[] outBytes = [44, 88, 22] + def os = new File(outputFileName).newOutputStream() + os.write(outBytes) + os.close() + assertEquals(3, new File(outputFileName).size()) + } +} From 4376424e512d9296cc2914049f3dcf8d00d55231 Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Wed, 6 Mar 2019 07:14:23 +0000 Subject: [PATCH 259/496] Adding XMLGregorianCalendar to LocalDate converters --- .../XmlGregorianCalendarConverter.java | 29 ++++++++++++ .../XmlGregorianCalendarConverterTest.java | 44 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 java-dates/src/main/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverter.java create mode 100644 java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java diff --git a/java-dates/src/main/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverter.java b/java-dates/src/main/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverter.java new file mode 100644 index 0000000000..7f7515ec4b --- /dev/null +++ b/java-dates/src/main/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverter.java @@ -0,0 +1,29 @@ +package com.baeldung.xmlgregoriancalendar; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import java.time.LocalDate; + +public class XmlGregorianCalendarConverter { + + public static void main(String[] args) throws DatatypeConfigurationException { + LocalDate localDate = LocalDate.now(); + System.out.println("localdate: " + localDate); + XMLGregorianCalendar xmlGregorianCalendar = fromLocalDate(localDate); + System.out.println("xmlGregorianCalendar: " + xmlGregorianCalendar); + + xmlGregorianCalendar.setTime(1, 1, 30); + System.out.println("xmlGregorianCalendar with time information: " + xmlGregorianCalendar); + LocalDate newLocalDate = fromXMLGregorianCalendar(xmlGregorianCalendar); + System.out.println("newLocalDate: " + newLocalDate); + } + + static XMLGregorianCalendar fromLocalDate(LocalDate localDate) throws DatatypeConfigurationException { + return DatatypeFactory.newInstance().newXMLGregorianCalendar(localDate.toString()); + } + + static LocalDate fromXMLGregorianCalendar(XMLGregorianCalendar xmlGregorianCalendar) { + return LocalDate.of(xmlGregorianCalendar.getYear(), xmlGregorianCalendar.getMonth(), xmlGregorianCalendar.getDay()); + } +} diff --git a/java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java b/java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java new file mode 100644 index 0000000000..f27c91be7e --- /dev/null +++ b/java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java @@ -0,0 +1,44 @@ +package com.baeldung.xmlgregoriancalendar; + +import org.junit.Test; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import java.time.LocalDate; + +import static com.baeldung.xmlgregoriancalendar.XmlGregorianCalendarConverter.fromLocalDate; +import static com.baeldung.xmlgregoriancalendar.XmlGregorianCalendarConverter.fromXMLGregorianCalendar; +import static org.assertj.core.api.Assertions.assertThat; + +public class XmlGregorianCalendarConverterTest { + + @Test + public void fromLocalDateToXMLGregorianCalendar() throws DatatypeConfigurationException { + LocalDate localDate = LocalDate.of(2017, 4, 25); + XMLGregorianCalendar xmlGregorianCalendar = fromLocalDate(localDate); + + assertThat(xmlGregorianCalendar.getYear()).isEqualTo(localDate.getYear()); + assertThat(xmlGregorianCalendar.getMonth()).isEqualTo(localDate.getMonthValue()); + assertThat(xmlGregorianCalendar.getDay()).isEqualTo(localDate.getDayOfMonth()); + } + + @Test + public void fromXMLGregorianCalendarToLocalDate() throws DatatypeConfigurationException { + XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar("2017-04-25"); + LocalDate localDate = fromXMLGregorianCalendar(xmlGregorianCalendar); + + assertThat(localDate.getYear()).isEqualTo(xmlGregorianCalendar.getYear()); + assertThat(localDate.getMonthValue()).isEqualTo(xmlGregorianCalendar.getMonth()); + assertThat(localDate.getDayOfMonth()).isEqualTo(xmlGregorianCalendar.getDay()); + } + + @Test + public void compositionOfFunctionsIsIdentity() throws DatatypeConfigurationException { // Only if we don't consider time + LocalDate localDate = LocalDate.of(2017, 4, 25); + XMLGregorianCalendar xmlGregorianCalendar = fromLocalDate(localDate); + LocalDate resultDate = fromXMLGregorianCalendar(xmlGregorianCalendar); + + assertThat(resultDate).isEqualTo(localDate); + } +} From e98cc8a407b33e59c5277b50f98f4ae7684e3e2c Mon Sep 17 00:00:00 2001 From: saukedia1 Date: Wed, 6 Mar 2019 15:11:21 +0530 Subject: [PATCH 260/496] BAEL-2011 Eclipse error: web.xml is missing and is set to true --- maven/maven-war-plugin-property/pom.xml | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 maven/maven-war-plugin-property/pom.xml diff --git a/maven/maven-war-plugin-property/pom.xml b/maven/maven-war-plugin-property/pom.xml new file mode 100644 index 0000000000..7063a4e247 --- /dev/null +++ b/maven/maven-war-plugin-property/pom.xml @@ -0,0 +1,29 @@ + + 4.0.0 + com.baeldung + maven-war-plugin-property + 0.0.1-SNAPSHOT + war + maven-war-plugin-property + + + + false + + + + + + maven-war-plugin + + 3.1.0 + + + false + + + + + \ No newline at end of file From 7a029078e6860742f08fb13e6f5da75fcb81788a Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Thu, 7 Mar 2019 22:49:44 +0530 Subject: [PATCH 261/496] Adding files for BAEL-2196 (#6477) * Adding files for BAEL-2196 * modified Package structure --- maven/compiler-plugin-java-9/pom.xml | 22 +++++++++++++++++++ .../maven/java9/MavenCompilerPlugin.java | 9 ++++++++ .../src/main/java/module-info.java | 3 +++ 3 files changed, 34 insertions(+) create mode 100644 maven/compiler-plugin-java-9/pom.xml create mode 100644 maven/compiler-plugin-java-9/src/main/java/com/baeldung/maven/java9/MavenCompilerPlugin.java create mode 100644 maven/compiler-plugin-java-9/src/main/java/module-info.java diff --git a/maven/compiler-plugin-java-9/pom.xml b/maven/compiler-plugin-java-9/pom.xml new file mode 100644 index 0000000000..5303cee82e --- /dev/null +++ b/maven/compiler-plugin-java-9/pom.xml @@ -0,0 +1,22 @@ + + 4.0.0 + com.baeldung + compiler-plugin-java-9 + 0.0.1-SNAPSHOT + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 9 + 9 + + + + + \ No newline at end of file diff --git a/maven/compiler-plugin-java-9/src/main/java/com/baeldung/maven/java9/MavenCompilerPlugin.java b/maven/compiler-plugin-java-9/src/main/java/com/baeldung/maven/java9/MavenCompilerPlugin.java new file mode 100644 index 0000000000..b460d6e38c --- /dev/null +++ b/maven/compiler-plugin-java-9/src/main/java/com/baeldung/maven/java9/MavenCompilerPlugin.java @@ -0,0 +1,9 @@ +package com.baeldung.maven.java9; + +import static javax.xml.XMLConstants.XML_NS_PREFIX; + +public class MavenCompilerPlugin { + public static void main(String[] args) { + System.out.println("The XML namespace prefix is: " + XML_NS_PREFIX); + } +} diff --git a/maven/compiler-plugin-java-9/src/main/java/module-info.java b/maven/compiler-plugin-java-9/src/main/java/module-info.java new file mode 100644 index 0000000000..afc1d45e71 --- /dev/null +++ b/maven/compiler-plugin-java-9/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.maven.java9 { + requires java.xml; +} \ No newline at end of file From 67ed044498250f2b62a55866d63efd45dd5c4119 Mon Sep 17 00:00:00 2001 From: eric-martin Date: Thu, 7 Mar 2019 21:52:47 -0600 Subject: [PATCH 262/496] BAEL-2755: Added design-patterns-2 module --- patterns/design-patterns-2/pom.xml | 25 +++++++++++++++++++ .../com/baeldung/nullobject/JmsRouter.java | 0 .../java/com/baeldung/nullobject/Message.java | 0 .../com/baeldung/nullobject/NullRouter.java | 0 .../java/com/baeldung/nullobject/Router.java | 0 .../baeldung/nullobject/RouterFactory.java | 0 .../baeldung/nullobject/RoutingHandler.java | 0 .../com/baeldung/nullobject/SmsRouter.java | 0 patterns/pom.xml | 1 + 9 files changed, 26 insertions(+) create mode 100644 patterns/design-patterns-2/pom.xml rename patterns/{design-patterns => design-patterns-2}/src/main/java/com/baeldung/nullobject/JmsRouter.java (100%) rename patterns/{design-patterns => design-patterns-2}/src/main/java/com/baeldung/nullobject/Message.java (100%) rename patterns/{design-patterns => design-patterns-2}/src/main/java/com/baeldung/nullobject/NullRouter.java (100%) rename patterns/{design-patterns => design-patterns-2}/src/main/java/com/baeldung/nullobject/Router.java (100%) rename patterns/{design-patterns => design-patterns-2}/src/main/java/com/baeldung/nullobject/RouterFactory.java (100%) rename patterns/{design-patterns => design-patterns-2}/src/main/java/com/baeldung/nullobject/RoutingHandler.java (100%) rename patterns/{design-patterns => design-patterns-2}/src/main/java/com/baeldung/nullobject/SmsRouter.java (100%) diff --git a/patterns/design-patterns-2/pom.xml b/patterns/design-patterns-2/pom.xml new file mode 100644 index 0000000000..2a0213065b --- /dev/null +++ b/patterns/design-patterns-2/pom.xml @@ -0,0 +1,25 @@ + + + 4.0.0 + design-patterns-2 + 1.0 + design-patterns-2 + jar + + + com.baeldung + patterns + 1.0.0-SNAPSHOT + .. + + + + + + + UTF-8 + 1.8 + 1.8 + + diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/JmsRouter.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/JmsRouter.java similarity index 100% rename from patterns/design-patterns/src/main/java/com/baeldung/nullobject/JmsRouter.java rename to patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/JmsRouter.java diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/Message.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Message.java similarity index 100% rename from patterns/design-patterns/src/main/java/com/baeldung/nullobject/Message.java rename to patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Message.java diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/NullRouter.java similarity index 100% rename from patterns/design-patterns/src/main/java/com/baeldung/nullobject/NullRouter.java rename to patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/NullRouter.java diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/Router.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Router.java similarity index 100% rename from patterns/design-patterns/src/main/java/com/baeldung/nullobject/Router.java rename to patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/Router.java diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/RouterFactory.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RouterFactory.java similarity index 100% rename from patterns/design-patterns/src/main/java/com/baeldung/nullobject/RouterFactory.java rename to patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RouterFactory.java diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/RoutingHandler.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RoutingHandler.java similarity index 100% rename from patterns/design-patterns/src/main/java/com/baeldung/nullobject/RoutingHandler.java rename to patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/RoutingHandler.java diff --git a/patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/SmsRouter.java similarity index 100% rename from patterns/design-patterns/src/main/java/com/baeldung/nullobject/SmsRouter.java rename to patterns/design-patterns-2/src/main/java/com/baeldung/nullobject/SmsRouter.java diff --git a/patterns/pom.xml b/patterns/pom.xml index 3c3bb6d5ea..111e72b9ca 100644 --- a/patterns/pom.xml +++ b/patterns/pom.xml @@ -17,6 +17,7 @@ front-controller intercepting-filter design-patterns + design-patterns-2 solid From b9c7d82e15f564fe2c5e45b41fa2ed8bc388c107 Mon Sep 17 00:00:00 2001 From: saukedia1 Date: Fri, 8 Mar 2019 15:57:20 +0530 Subject: [PATCH 263/496] BAEL-2011 Eclipse error: web.xml is missing and is set to true --- maven/{maven-war-plugin-property => maven-war-plugin}/pom.xml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename maven/{maven-war-plugin-property => maven-war-plugin}/pom.xml (100%) diff --git a/maven/maven-war-plugin-property/pom.xml b/maven/maven-war-plugin/pom.xml similarity index 100% rename from maven/maven-war-plugin-property/pom.xml rename to maven/maven-war-plugin/pom.xml From 558e316623b1a28e7ef81d54853d72c3f34b1d61 Mon Sep 17 00:00:00 2001 From: saukedia1 Date: Fri, 8 Mar 2019 16:02:36 +0530 Subject: [PATCH 264/496] BAEL-2011 Eclipse error: web.xml is missing and is set to true --- maven/maven-war-plugin/pom.xml | 52 +++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/maven/maven-war-plugin/pom.xml b/maven/maven-war-plugin/pom.xml index 7063a4e247..5169a21e78 100644 --- a/maven/maven-war-plugin/pom.xml +++ b/maven/maven-war-plugin/pom.xml @@ -1,29 +1,29 @@ - 4.0.0 - com.baeldung - maven-war-plugin-property - 0.0.1-SNAPSHOT - war - maven-war-plugin-property + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung + maven-war-plugin-property + 0.0.1-SNAPSHOT + war + maven-war-plugin-property + + + + false + - - - false - - - - - - maven-war-plugin - - 3.1.0 - - - false - - - - + + + + maven-war-plugin + + 3.1.0 + + + false + + + + \ No newline at end of file From b42c2d3a5fe278be65c77e6d3cec44a7b98e6557 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Fri, 8 Mar 2019 15:33:10 +0400 Subject: [PATCH 265/496] primitive map libraries --- libraries/pom.xml | 15 ++++++ .../baeldung/primitives/PrimitiveMaps.java | 54 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java diff --git a/libraries/pom.xml b/libraries/pom.xml index c7ef64bc59..a49570b029 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -373,6 +373,21 @@ eclipse-collections ${eclipse-collections.version} + + net.sf.trove4j + trove4j + 3.0.2 + + + it.unimi.dsi + fastutil + 8.1.0 + + + colt + colt + 1.2.0 + io.vavr vavr diff --git a/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java b/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java new file mode 100644 index 0000000000..4ee10997c2 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java @@ -0,0 +1,54 @@ +package com.baeldung.primitives; + +import cern.colt.map.AbstractIntDoubleMap; +import cern.colt.map.OpenIntDoubleHashMap; +import gnu.trove.map.TDoubleIntMap; +import gnu.trove.map.hash.TDoubleIntHashMap; +import org.eclipse.collections.api.map.primitive.*; +import org.eclipse.collections.impl.factory.primitive.*; + +public class PrimitiveMaps { + + public static void main(String[] args) { + + eclipseCollectionsMap(); + troveMap(); + coltMap(); + } + + private static void coltMap() { + AbstractIntDoubleMap map = new OpenIntDoubleHashMap(); + map.put(1, 4.5); + } + + private static void eclipseCollectionsMap() { + MutableObjectDoubleMap doubleMap = ObjectDoubleMaps.mutable.empty(); + doubleMap.put("1", 1.0d); + doubleMap.put("2", 2.0d); + + MutableObjectIntMap booleanMap = ObjectIntMaps.mutable.empty(); + booleanMap.put("ok", 1); + + MutableIntIntMap mutableIntIntMap = IntIntMaps.mutable.empty(); + mutableIntIntMap.addToValue(1, 1); + + ImmutableIntIntMap immutableIntIntMap = IntIntMaps.immutable.empty(); + + MutableObjectIntMap intObject = ObjectIntMaps.mutable.empty(); + intObject.addToValue("price", 2); + } + + private static void troveMap() { + + double[] doubles = new double[] {1.2, 4.5, 0.3}; + int[] ints = new int[] {1, 4, 0}; + + TDoubleIntMap doubleIntMap = new TDoubleIntHashMap(doubles, ints); + + doubleIntMap.adjustValue(1.2, 1); + doubleIntMap.adjustValue(4.5, 4); + doubleIntMap.adjustValue(0.3, 0); + + System.out.println(doubleIntMap); + } +} From 786888f7c33d5bd147654565a5a810dfba8ad0b6 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Fri, 8 Mar 2019 08:39:44 -0300 Subject: [PATCH 266/496] BAEL-12777 Upgrade parent-spring-5 version: * Migrated parent-spring-5 version (spring-core and spring-security) * Cleaned spring-security version being used in some modules. Now using the parent version --- parent-spring-5/pom.xml | 4 ++-- spring-mvc-simple/pom.xml | 3 +-- spring-security-mvc-custom/pom.xml | 11 ++++------- spring-security-mvc-jsonview/pom.xml | 11 ++++------- spring-security-mvc-login/pom.xml | 9 ++++----- spring-security-rest/pom.xml | 7 +++---- spring-static-resources/pom.xml | 9 +++------ 7 files changed, 21 insertions(+), 33 deletions(-) diff --git a/parent-spring-5/pom.xml b/parent-spring-5/pom.xml index 5d7a3b66b3..3178682d34 100644 --- a/parent-spring-5/pom.xml +++ b/parent-spring-5/pom.xml @@ -29,10 +29,10 @@ - 5.1.2.RELEASE + 5.1.4.RELEASE 5.0.2 2.9.6 - 5.1.2.RELEASE + 5.1.4.RELEASE \ No newline at end of file diff --git a/spring-mvc-simple/pom.xml b/spring-mvc-simple/pom.xml index 8c2661cc27..b9ed3a3e81 100644 --- a/spring-mvc-simple/pom.xml +++ b/spring-mvc-simple/pom.xml @@ -17,7 +17,7 @@ org.springframework spring-oxm - ${spring-oxm.version} + ${spring.version} com.sun.mail @@ -181,7 +181,6 @@ 1.4.9 5.1.0 20180130 - 5.0.2.RELEASE 3.0.8 diff --git a/spring-security-mvc-custom/pom.xml b/spring-security-mvc-custom/pom.xml index b4239fb2b8..7c60a8e18a 100644 --- a/spring-security-mvc-custom/pom.xml +++ b/spring-security-mvc-custom/pom.xml @@ -21,17 +21,17 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-taglibs - ${org.springframework.security.version} + ${spring-security.version} @@ -144,7 +144,7 @@ org.springframework.security spring-security-test - ${org.springframework.security.version} + ${spring-security.version} test @@ -192,9 +192,6 @@ - - 5.0.6.RELEASE - 3.1.0 1.2 diff --git a/spring-security-mvc-jsonview/pom.xml b/spring-security-mvc-jsonview/pom.xml index 7f1129128f..b6d3e7e399 100644 --- a/spring-security-mvc-jsonview/pom.xml +++ b/spring-security-mvc-jsonview/pom.xml @@ -38,17 +38,17 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-taglibs - ${org.springframework.security.version} + ${spring-security.version} @@ -133,7 +133,7 @@ org.springframework.security spring-security-test - ${org.springframework.security.version} + ${spring-security.version} test @@ -206,9 +206,6 @@ - - 5.0.5.RELEASE - 3.1.0 1.2 diff --git a/spring-security-mvc-login/pom.xml b/spring-security-mvc-login/pom.xml index bbdff6fc2f..048297bbd4 100644 --- a/spring-security-mvc-login/pom.xml +++ b/spring-security-mvc-login/pom.xml @@ -21,17 +21,17 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-taglibs - ${org.springframework.security.version} + ${spring-security.version} @@ -116,7 +116,7 @@ org.springframework.security spring-security-test - ${org.springframework.security.version} + ${spring-security.version} test @@ -175,7 +175,6 @@ - 5.0.5.RELEASE 3.1.0 diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml index 37c743e896..24f1c5807a 100644 --- a/spring-security-rest/pom.xml +++ b/spring-security-rest/pom.xml @@ -21,12 +21,12 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} @@ -144,7 +144,7 @@ org.springframework.security spring-security-test - ${org.springframework.security.version} + ${spring-security.version} test @@ -274,7 +274,6 @@ - 5.1.0.RELEASE 0.25.0.RELEASE diff --git a/spring-static-resources/pom.xml b/spring-static-resources/pom.xml index aedf88e384..fc2b3336bc 100644 --- a/spring-static-resources/pom.xml +++ b/spring-static-resources/pom.xml @@ -20,17 +20,17 @@ org.springframework.security spring-security-web - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-config - ${org.springframework.security.version} + ${spring-security.version} org.springframework.security spring-security-taglibs - ${org.springframework.security.version} + ${spring-security.version} @@ -196,9 +196,6 @@ - - 5.0.6.RELEASE - 1.8.9 2.3.2-b02 From ae6c29dd19fcb5edf0182096f3f3b7b0f8a5c6e8 Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Fri, 8 Mar 2019 11:20:52 -0300 Subject: [PATCH 267/496] Guide to Stream.reduce() (#6480) * Initial Commit * Update Application.java * Update Application.java --- java-streams-2/pom.xml | 39 +++++++++ .../reduce/application/Application.java | 39 +++++++++ .../benchmarks/JMHStreamReduceBenchMark.java | 52 ++++++++++++ .../com/baeldung/reduce/entities/User.java | 25 ++++++ .../reduce/utilities/NumberUtils.java | 52 ++++++++++++ .../reduce/tests/StreamReduceUnitTest.java | 79 +++++++++++++++++++ 6 files changed, 286 insertions(+) create mode 100644 java-streams-2/pom.xml create mode 100644 java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java create mode 100644 java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java create mode 100644 java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java create mode 100644 java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java create mode 100644 java-streams-2/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java diff --git a/java-streams-2/pom.xml b/java-streams-2/pom.xml new file mode 100644 index 0000000000..cd89a1a80f --- /dev/null +++ b/java-streams-2/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + com.baeldung.javastreams2 + javastreams2 + 1.0 + jar + + + org.openjdk.jmh + jmh-core + 1.21 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.21 + + + junit + junit + 4.12 + test + jar + + + org.assertj + assertj-core + 3.11.1 + test + + + Stream Reduce + + UTF-8 + 1.8 + 1.8 + + \ No newline at end of file diff --git a/java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java b/java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java new file mode 100644 index 0000000000..79c557524d --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/reduce/application/Application.java @@ -0,0 +1,39 @@ +package com.baeldung.reduce.application; + +import com.baeldung.reduce.entities.User; +import com.baeldung.reduce.utilities.NumberUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Application { + + public static void main(String[] args) { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result1 = numbers.stream().reduce(0, (subtotal, element) -> subtotal + element); + System.out.println(result1); + + int result2 = numbers.stream().reduce(0, Integer::sum); + System.out.println(result2); + + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result3 = letters.stream().reduce("", (partialString, element) -> partialString + element); + System.out.println(result3); + + String result4 = letters.stream().reduce("", String::concat); + System.out.println(result4); + + String result5 = letters.stream().reduce("", (partialString, element) -> partialString.toUpperCase() + element.toUpperCase()); + System.out.println(result5); + + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + int result6 = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result6); + + String result7 = letters.parallelStream().reduce("", String::concat); + System.out.println(result7); + + int result8 = users.parallelStream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + System.out.println(result8); + } +} diff --git a/java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java b/java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java new file mode 100644 index 0000000000..af4a9276a9 --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/reduce/benchmarks/JMHStreamReduceBenchMark.java @@ -0,0 +1,52 @@ +package com.baeldung.reduce.benchmarks; + +import com.baeldung.reduce.entities.User; +import java.util.ArrayList; +import java.util.List; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +public class JMHStreamReduceBenchMark { + + private final List userList = createUsers(); + + public static void main(String[] args) throws RunnerException { + + Options options = new OptionsBuilder() + .include(JMHStreamReduceBenchMark.class.getSimpleName()).threads(1) + .forks(1).shouldFailOnError(true).shouldDoGC(true) + .jvmArgs("-server").build(); + new Runner(options).run(); + } + + private List createUsers() { + List users = new ArrayList<>(); + for (int i = 0; i <= 1000000; i++) { + users.add(new User("John" + i, i)); + } + return users; + } + + @Benchmark + public Integer executeReduceOnParallelizedStream() { + return this.userList + .parallelStream() + .reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + } + + @Benchmark + public Integer executeReduceOnSequentialStream() { + return this.userList + .stream() + .reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + } +} diff --git a/java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java b/java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java new file mode 100644 index 0000000000..a17c6a02b6 --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/reduce/entities/User.java @@ -0,0 +1,25 @@ +package com.baeldung.reduce.entities; + +public class User { + + private final String name; + private final int age; + + public User(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return "User{" + "name=" + name + ", age=" + age + '}'; + } +} diff --git a/java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java b/java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java new file mode 100644 index 0000000000..a7a4b8df29 --- /dev/null +++ b/java-streams-2/src/main/java/com/baeldung/reduce/utilities/NumberUtils.java @@ -0,0 +1,52 @@ +package com.baeldung.reduce.utilities; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.logging.Level; +import java.util.logging.Logger; + +public abstract class NumberUtils { + + private static final Logger LOGGER = Logger.getLogger(NumberUtils.class.getName()); + + public static int divideListElements(List values, Integer divider) { + return values.stream() + .reduce(0, (a, b) -> { + try { + return a / divider + b / divider; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return 0; + }); + } + + public static int divideListElementsWithExtractedTryCatchBlock(List values, int divider) { + return values.stream().reduce(0, (a, b) -> divide(a, divider) + divide(b, divider)); + } + + public static int divideListElementsWithApplyFunctionMethod(List values, int divider) { + BiFunction division = (a, b) -> a / b; + return values.stream().reduce(0, (a, b) -> applyFunction(division, a, divider) + applyFunction(division, b, divider)); + } + + private static int divide(int value, int factor) { + int result = 0; + try { + result = value / factor; + } catch (ArithmeticException e) { + LOGGER.log(Level.INFO, "Arithmetic Exception: Division by Zero"); + } + return result; + } + + private static int applyFunction(BiFunction function, int a, int b) { + try { + return function.apply(a, b); + } + catch(Exception e) { + LOGGER.log(Level.INFO, "Exception thrown!"); + } + return 0; + } +} diff --git a/java-streams-2/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java b/java-streams-2/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java new file mode 100644 index 0000000000..564d614017 --- /dev/null +++ b/java-streams-2/src/test/java/com/baeldung/reduce/tests/StreamReduceUnitTest.java @@ -0,0 +1,79 @@ +package com.baeldung.reduce.tests; + +import com.baeldung.reduce.entities.User; +import com.baeldung.reduce.utilities.NumberUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + +public class StreamReduceUnitTest { + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorLambda_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result = numbers.stream().reduce(0, (subtotal, element) -> subtotal + element); + assertThat(result).isEqualTo(21); + } + + @Test + public void givenIntegerList_whenReduceWithSumAccumulatorMethodReference_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + int result = numbers.stream().reduce(0, Integer::sum); + assertThat(result).isEqualTo(21); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorLambda_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.stream().reduce("", (partialString, element) -> partialString + element); + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithConcatenatorAccumulatorMethodReference_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.stream().reduce("", String::concat); + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenStringList_whenReduceWithUppercaseConcatenatorAccumulator_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.stream().reduce("", (partialString, element) -> partialString.toUpperCase() + element.toUpperCase()); + assertThat(result).isEqualTo("ABCDE"); + } + + @Test + public void givenUserList_whenReduceWithAgeAccumulatorAndSumCombiner_thenCorrect() { + List users = Arrays.asList(new User("John", 30), new User("Julie", 35)); + int result = users.stream().reduce(0, (partialAgeResult, user) -> partialAgeResult + user.getAge(), Integer::sum); + assertThat(result).isEqualTo(65); + } + + @Test + public void givenStringList_whenReduceWithParallelStream_thenCorrect() { + List letters = Arrays.asList("a", "b", "c", "d", "e"); + String result = letters.parallelStream().reduce("", String::concat); + assertThat(result).isEqualTo("abcde"); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElements_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + assertThat(NumberUtils.divideListElements(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenNumberUtilsClass_whenCalledDivideListElementsWithExtractedTryCatchBlock_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + assertThat(NumberUtils.divideListElementsWithExtractedTryCatchBlock(numbers, 1)).isEqualTo(21); + } + + @Test + public void givenStream_whneCalleddivideListElementsWithApplyFunctionMethod_thenCorrect() { + List numbers = Arrays.asList(1, 2, 3, 4, 5, 6); + assertThat(NumberUtils.divideListElementsWithApplyFunctionMethod(numbers, 1)).isEqualTo(21); + } +} From 3fd4fb1cdaa7336358a259134ed5547a6fb57b2c Mon Sep 17 00:00:00 2001 From: Johan Janssen Date: Fri, 8 Mar 2019 15:30:10 +0100 Subject: [PATCH 268/496] Kotlin split list in pairs examples. (#6368) * Kotlin split list in pairs examples. * Renamed some items. --- .../com/baeldung/splitting/SplittingTest.kt | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 core-kotlin/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt diff --git a/core-kotlin/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt new file mode 100644 index 0000000000..a9ddc99992 --- /dev/null +++ b/core-kotlin/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt @@ -0,0 +1,99 @@ +package com.baeldung.lambda + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class SplittingTest { + private val evenList = listOf(0, "a", 1, "b", 2, "c"); + + private val unevenList = listOf(0, "a", 1, "b", 2, "c", 3); + + private fun verifyList(resultList: List>) { + assertEquals("[[0, a], [1, b], [2, c]]", resultList.toString()) + } + + private fun verifyPartialList(resultList: List>) { + assertEquals("[[0, a], [1, b], [2, c], [3]]", resultList.toString()) + } + + @Test + fun whenChunked_thenListIsSplit() { + val resultList = evenList.chunked(2) + verifyList(resultList) + } + + @Test + fun whenUnevenChunked_thenListIsSplit() { + val resultList = unevenList.chunked(2) + verifyPartialList(resultList) + } + + @Test + fun whenWindowed_thenListIsSplit() { + val resultList = evenList.windowed(2, 2) + verifyList(resultList) + } + + @Test + fun whenUnevenPartialWindowed_thenListIsSplit() { + val resultList = unevenList.windowed(2, 2, partialWindows = true) + verifyPartialList(resultList) + } + + @Test + fun whenUnevenWindowed_thenListIsSplit() { + val resultList = unevenList.windowed(2, 2, partialWindows = false) + verifyList(resultList) + } + + @Test + fun whenGroupByWithAscendingNumbers_thenListIsSplit() { + val numberList = listOf(1, 2, 3, 4, 5, 6); + val resultList = numberList.groupBy { (it + 1) / 2 } + assertEquals("[[1, 2], [3, 4], [5, 6]]", resultList.values.toString()) + assertEquals("[1, 2, 3]", resultList.keys.toString()) + } + + @Test + fun whenGroupByWithAscendingNumbersUneven_thenListIsSplit() { + val numberList = listOf(1, 2, 3, 4, 5, 6, 7); + val resultList = numberList.groupBy { (it + 1) / 2 }.values + assertEquals("[[1, 2], [3, 4], [5, 6], [7]]", resultList.toString()) + } + + @Test + fun whenGroupByWithRandomNumbers_thenListIsSplitInWrongWay() { + val numberList = listOf(1, 3, 8, 20, 23, 30); + val resultList = numberList.groupBy { (it + 1) / 2 } + assertEquals("[[1], [3], [8], [20], [23], [30]]", resultList.values.toString()) + assertEquals("[1, 2, 4, 10, 12, 15]", resultList.keys.toString()) + } + + @Test + fun whenWithIndexGroupBy_thenListIsSplit() { + val resultList = evenList.withIndex() + .groupBy { it.index / 2 } + .map { it.value.map { it.value } } + verifyList(resultList) + } + + @Test + fun whenWithIndexGroupByUneven_thenListIsSplit() { + val resultList = unevenList.withIndex() + .groupBy { it.index / 2 } + .map { it.value.map { it.value } } + verifyPartialList(resultList) + } + + @Test + fun whenFoldIndexed_thenListIsSplit() { + val resultList = evenList.foldIndexed(ArrayList>(evenList.size / 2)) { index, acc, item -> + if (index % 2 == 0) { + acc.add(ArrayList(2)) + } + acc.last().add(item) + acc + } + verifyList(resultList) + } +} \ No newline at end of file From 4ec4fdb72bfc402fe1c3c1ea9dde8c59eced9f92 Mon Sep 17 00:00:00 2001 From: Wosin Date: Fri, 8 Mar 2019 23:20:37 +0100 Subject: [PATCH 269/496] Bael 43 (#6423) * BAEL-43: Apache Spark with Spring Cloud Data Flow * Replaced functions with lambdas + removed unnecessary type casting. --- .../apache-spark-job/pom.xml | 36 +++++++++++++++++ .../spring/cloud/PiApproximation.java | 39 +++++++++++++++++++ spring-cloud-data-flow/pom.xml | 1 + 3 files changed, 76 insertions(+) create mode 100644 spring-cloud-data-flow/apache-spark-job/pom.xml create mode 100644 spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java diff --git a/spring-cloud-data-flow/apache-spark-job/pom.xml b/spring-cloud-data-flow/apache-spark-job/pom.xml new file mode 100644 index 0000000000..390b7ebdc6 --- /dev/null +++ b/spring-cloud-data-flow/apache-spark-job/pom.xml @@ -0,0 +1,36 @@ + + + + spring-cloud-data-flow + com.baeldung + 0.0.1-SNAPSHOT + + 4.0.0 + + apache-spark-job + + + org.springframework.cloud + spring-cloud-task-core + 2.0.0.RELEASE + + + org.apache.spark + spark-core_2.10 + 1.6.2 + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + + \ No newline at end of file diff --git a/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java b/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java new file mode 100644 index 0000000000..dfead21728 --- /dev/null +++ b/spring-cloud-data-flow/apache-spark-job/src/main/java/com/baeldung/spring/cloud/PiApproximation.java @@ -0,0 +1,39 @@ +package com.baeldung.spring.cloud; + +import org.apache.spark.SparkConf; +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.api.java.JavaSparkContext; +import org.apache.spark.api.java.function.Function; +import org.apache.spark.api.java.function.Function2; +import org.apache.spark.rdd.RDD; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class PiApproximation { + public static void main(String[] args) { + SparkConf conf = new SparkConf().setAppName("BaeldungPIApproximation"); + JavaSparkContext context = new JavaSparkContext(conf); + int slices = args.length >= 1 ? Integer.valueOf(args[0]) : 2; + int n = (100000L * slices) > Integer.MAX_VALUE ? Integer.MAX_VALUE : 100000 * slices; + + List xs = IntStream.rangeClosed(0, n) + .mapToObj(element -> Integer.valueOf(element)) + .collect(Collectors.toList()); + + JavaRDD dataSet = context.parallelize(xs, slices); + + JavaRDD pointsInsideTheCircle = dataSet.map(integer -> { + double x = Math.random() * 2 - 1; + double y = Math.random() * 2 - 1; + return (x*x + y*y ) < 1 ? 1: 0; + }); + + int count = pointsInsideTheCircle.reduce((integer, integer2) -> integer + integer2); + + System.out.println("The pi was estimated as:" + count / n); + + context.stop(); + } +} diff --git a/spring-cloud-data-flow/pom.xml b/spring-cloud-data-flow/pom.xml index daf8ebd2c8..36a780c28d 100644 --- a/spring-cloud-data-flow/pom.xml +++ b/spring-cloud-data-flow/pom.xml @@ -20,6 +20,7 @@ log-sink batch-job etl + apache-spark-job From 2c4d334dc3f11781393d354773fbb681d7c98794 Mon Sep 17 00:00:00 2001 From: soufiane-cheouati <46105138+soufiane-cheouati@users.noreply.github.com> Date: Fri, 8 Mar 2019 22:30:42 +0000 Subject: [PATCH 270/496] Reversing binary tree classes (#6467) * Add files via upload * Add files via upload * Add files via upload --- .../algorithms/reversingtree/TreeNode.java | 42 ++++++++++++ .../reversingtree/TreeReverser.java | 68 +++++++++++++++++++ .../reversingtree/TreeReverserUnitTest.java | 33 +++++++++ 3 files changed, 143 insertions(+) create mode 100644 algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java create mode 100644 algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java create mode 100644 algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java new file mode 100644 index 0000000000..7905b752a9 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java @@ -0,0 +1,42 @@ +package com.baeldung.algorithms.reversingtree; + +public class TreeNode { + + private int value; + private TreeNode rightChild; + private TreeNode leftChild; + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public TreeNode getRightChild() { + return rightChild; + } + + public void setRightChild(TreeNode rightChild) { + this.rightChild = rightChild; + } + + public TreeNode getLeftChild() { + return leftChild; + } + + public void setLeftChild(TreeNode leftChild) { + this.leftChild = leftChild; + } + + public TreeNode(int value, TreeNode rightChild, TreeNode leftChild) { + this.value = value; + this.rightChild = rightChild; + this.leftChild = leftChild; + } + + public TreeNode(int value) { + this.value = value; + } +} diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java new file mode 100644 index 0000000000..6d3a9ddd31 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java @@ -0,0 +1,68 @@ +package com.baeldung.algorithms.reversingtree; + +import java.util.LinkedList; + +public class TreeReverser { + + public TreeNode createBinaryTree() { + + TreeNode leaf1 = new TreeNode(3); + TreeNode leaf2 = new TreeNode(1); + TreeNode leaf3 = new TreeNode(9); + TreeNode leaf4 = new TreeNode(6); + + TreeNode nodeLeft = new TreeNode(2, leaf1, leaf2); + TreeNode nodeRight = new TreeNode(7, leaf3, leaf4); + + TreeNode root = new TreeNode(4, nodeRight, nodeLeft); + + return root; + } + + public void reverseRecursive(TreeNode treeNode) { + if (treeNode == null) { + return; + } + + TreeNode temp = treeNode.getLeftChild(); + treeNode.setLeftChild(treeNode.getRightChild()); + treeNode.setRightChild(temp); + + reverseRecursive(treeNode.getLeftChild()); + reverseRecursive(treeNode.getRightChild()); + } + + public void reverseIterative(TreeNode treeNode) { + LinkedList queue = new LinkedList(); + + if (treeNode != null) { + queue.add(treeNode); + } + + while (!queue.isEmpty()) { + + TreeNode node = queue.poll(); + if (node.getLeftChild() != null) + queue.add(node.getLeftChild()); + if (node.getRightChild() != null) + queue.add(node.getRightChild()); + + TreeNode temp = node.getLeftChild(); + node.setLeftChild(node.getRightChild()); + node.setRightChild(temp); + } + } + + public String toString(TreeNode root) { + if (root == null) { + return ""; + } + + StringBuffer buffer = new StringBuffer(String.valueOf(root.getValue())).append(" "); + + buffer.append(toString(root.getLeftChild())); + buffer.append(toString(root.getRightChild())); + + return buffer.toString(); + } +} diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java new file mode 100644 index 0000000000..cbc265fae1 --- /dev/null +++ b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.algorithms.reversingtree; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class TreeReverserUnitTest { + + @Test + public void givenTreeWhenReversingRecursivelyThenReversed() { + TreeReverser reverser = new TreeReverser(); + + TreeNode treeNode = reverser.createBinaryTree(); + + reverser.reverseRecursive(treeNode); + + assertEquals("4 7 9 6 2 3 1", reverser.toString(treeNode) + .trim()); + } + + @Test + public void givenTreeWhenReversingIterativelyThenReversed() { + TreeReverser reverser = new TreeReverser(); + + TreeNode treeNode = reverser.createBinaryTree(); + + reverser.reverseIterative(treeNode); + + assertEquals("4 7 9 6 2 3 1", reverser.toString(treeNode) + .trim()); + } + +} From 8f54420e95d5012319dae1a27193234722e126b2 Mon Sep 17 00:00:00 2001 From: Juan Moreno Date: Sat, 9 Mar 2019 00:50:03 -0300 Subject: [PATCH 271/496] Added sample code for BAEL-1122 (#6468) --- spring-all/pom.xml | 18 +++++++------ .../spring/PropertiesWithJavaConfig.java | 1 + .../main/resources/configForProperties.xml | 2 +- ...lePropertiesJavaConfigIntegrationTest.java | 25 +++++++++++++++++++ ...plePropertiesXmlConfigIntegrationTest.java | 21 ++++++++++++++++ 5 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesJavaConfigIntegrationTest.java create mode 100644 spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java diff --git a/spring-all/pom.xml b/spring-all/pom.xml index 5872fbdac5..8c88efb970 100644 --- a/spring-all/pom.xml +++ b/spring-all/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-all 0.1-SNAPSHOT @@ -47,12 +47,16 @@ org.springframework spring-websocket - - + + org.springframework spring-messaging - - + + + javax.annotation + javax.annotation-api + ${annotation-api.version} + org.springframework @@ -227,13 +231,13 @@ - + org.baeldung.sample.App 5.0.6.RELEASE 1.2.0.RELEASE - + 1.3.2 5.2.5.Final diff --git a/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithJavaConfig.java b/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithJavaConfig.java index 08626bb4d2..6589143a94 100644 --- a/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithJavaConfig.java +++ b/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithJavaConfig.java @@ -7,6 +7,7 @@ import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; @Configuration @PropertySource("classpath:foo.properties") +@PropertySource("classpath:bar.properties") public class PropertiesWithJavaConfig { public PropertiesWithJavaConfig() { diff --git a/spring-all/src/main/resources/configForProperties.xml b/spring-all/src/main/resources/configForProperties.xml index 0f766665eb..459aea3ec6 100644 --- a/spring-all/src/main/resources/configForProperties.xml +++ b/spring-all/src/main/resources/configForProperties.xml @@ -7,7 +7,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd" > - + diff --git a/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesJavaConfigIntegrationTest.java b/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesJavaConfigIntegrationTest.java new file mode 100644 index 0000000000..9cb41c20f7 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesJavaConfigIntegrationTest.java @@ -0,0 +1,25 @@ +package org.baeldung.properties.multiple; + +import org.baeldung.properties.spring.PropertiesWithJavaConfig; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringJUnitConfig(PropertiesWithJavaConfig.class) +public class MultiplePropertiesJavaConfigIntegrationTest { + + @Value("${key.something}") + private String something; + + @Value("${key.something2}") + private String something2; + + + @Test + public void whenReadInjectedValues_thenGetCorrectValues() { + assertThat(something).isEqualTo("val"); + assertThat(something2).isEqualTo("val2"); + } +} diff --git a/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java b/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java new file mode 100644 index 0000000000..b4f81f3541 --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java @@ -0,0 +1,21 @@ +package org.baeldung.properties.multiple; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringJUnitConfig(locations = "classpath:configForProperties.xml") +public class MultiplePropertiesXmlConfigIntegrationTest { + + @Value("${key.something}") private String something; + + @Value("${key.something2}") private String something2; + + @Test + public void whenReadInjectedValues_thenGetCorrectValues() { + assertThat(something).isEqualTo("val"); + assertThat(something2).isEqualTo("val2"); + } +} From 02fd91ad35810cfe06d8b2e28a740957a8437ad5 Mon Sep 17 00:00:00 2001 From: Ganesh Pagade Date: Sat, 9 Mar 2019 14:59:08 +0530 Subject: [PATCH 272/496] review comments --- .../org/baeldung/gson/entities/MyClass.java | 36 +++++++++++++---- .../gson/advance/GsonAdvanceUnitTest.java | 40 +++++++++++-------- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/gson/src/main/java/org/baeldung/gson/entities/MyClass.java b/gson/src/main/java/org/baeldung/gson/entities/MyClass.java index 827ca10cb0..997f4c3f26 100644 --- a/gson/src/main/java/org/baeldung/gson/entities/MyClass.java +++ b/gson/src/main/java/org/baeldung/gson/entities/MyClass.java @@ -1,14 +1,18 @@ package org.baeldung.gson.entities; +import java.util.Objects; + public class MyClass { private int id; - private String[] strings; + private String name; - public MyClass() { - id = 1; - strings = new String[] { "a", "b" }; + public MyClass(int id, String name) { + this.id = id; + this.name = name; } + public MyClass() { } + public int getId() { return id; } @@ -17,11 +21,27 @@ public class MyClass { this.id = id; } - public String[] getStrings() { - return strings; + public String getName() { + return name; } - public void setStrings(String[] strings) { - this.strings = strings; + public void setName(String name) { + this.name = name; + } + + @Override public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MyClass myClass = (MyClass) o; + return id == myClass.id && Objects.equals(name, myClass.name); + } + + @Override public int hashCode() { + + return Objects.hash(id, name); } } diff --git a/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java b/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java index 020118aa2b..3bf2afbe4a 100644 --- a/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java +++ b/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java @@ -8,6 +8,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.baeldung.gson.entities.Animal; import org.baeldung.gson.entities.Cow; @@ -18,40 +19,42 @@ import org.junit.Test; public class GsonAdvanceUnitTest { - @Test public void givenListOfMyClass_whenSerializing_thenCorrect() { - List list = new ArrayList<>(); - list.add(new MyClass()); - list.add(new MyClass()); + @Test + public void givenListOfMyClass_whenSerializing_thenCorrect() { + List list = Arrays.asList(new MyClass(1, "name1"), new MyClass(2, "name2")); Gson gson = new Gson(); String jsonString = gson.toJson(list); - String expectedString = "[{\"id\":1,\"strings\":[\"a\",\"b\"]},{\"id\":1,\"strings\":[\"a\",\"b\"]}]"; + String expectedString = "[{\"id\":1,\"name\":\"name1\"},{\"id\":2,\"name\":\"name2\"}]"; assertEquals(expectedString, jsonString); } @Test(expected = ClassCastException.class) public void givenJsonString_whenIncorrectDeserializing_thenThrowClassCastException() { - String inputString = "[{\"id\":1,\"strings\":[\"a\",\"b\"]},{\"id\":1,\"strings\":[\"a\",\"b\"]}]"; + String inputString = "[{\"id\":1,\"name\":\"name1\"},{\"id\":2,\"name\":\"name2\"}]"; Gson gson = new Gson(); - List list = gson.fromJson(inputString, ArrayList.class); + List outputList = gson.fromJson(inputString, ArrayList.class); - assertEquals(1, list.get(0).getId()); + assertEquals(1, outputList.get(0).getId()); } - @Test public void givenJsonString_whenDeserializing_thenReturnListOfMyClass() { - String inputString = "[{\"id\":1,\"strings\":[\"a\",\"b\"]},{\"id\":1,\"strings\":[\"a\",\"b\"]}]"; + @Test + public void givenJsonString_whenDeserializing_thenReturnListOfMyClass() { + String inputString = "[{\"id\":1,\"name\":\"name1\"},{\"id\":2,\"name\":\"name2\"}]"; + List inputList = Arrays.asList(new MyClass(1, "name1"), new MyClass(2, "name2")); + Type listOfMyClassObject = new TypeToken>() {}.getType(); Gson gson = new Gson(); - List list = gson.fromJson(inputString, listOfMyClassObject); + List outputList = gson.fromJson(inputString, listOfMyClassObject); - assertEquals(2, list.size()); - assertEquals(1, list.get(0).getId()); + assertEquals(inputList, outputList); } - @Test public void givenPolymorphicList_whenSerializeWithTypeAdapter_thenCorrect() { + @Test + public void givenPolymorphicList_whenSerializeWithTypeAdapter_thenCorrect() { String expectedString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]"; List inList = new ArrayList<>(); @@ -63,7 +66,8 @@ public class GsonAdvanceUnitTest { assertEquals(expectedString, jsonString); } - @Test public void givenPolymorphicList_whenDeserializeWithTypeAdapter_thenCorrect() { + @Test + public void givenPolymorphicList_whenDeserializeWithTypeAdapter_thenCorrect() { String inputString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]"; AnimalDeserializer deserializer = new AnimalDeserializer("type"); @@ -79,7 +83,8 @@ public class GsonAdvanceUnitTest { assertTrue(outList.get(0) instanceof Dog); } - @Test public void givenPolymorphicList_whenSerializeWithRuntimeTypeAdapter_thenCorrect() { + @Test + public void givenPolymorphicList_whenSerializeWithRuntimeTypeAdapter_thenCorrect() { String expectedString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]"; List inList = new ArrayList<>(); @@ -90,7 +95,8 @@ public class GsonAdvanceUnitTest { assertEquals(expectedString, jsonString); } - @Test public void givenPolymorphicList_whenDeserializeWithRuntimeTypeAdapter_thenCorrect() { + @Test + public void givenPolymorphicList_whenDeserializeWithRuntimeTypeAdapter_thenCorrect() { String inputString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]"; Type listOfAnimals = new TypeToken>() {}.getType(); From 213349420b947a8d749eb4d2a51337bc5b80a870 Mon Sep 17 00:00:00 2001 From: Ganesh Pagade Date: Sat, 9 Mar 2019 15:06:07 +0530 Subject: [PATCH 273/496] review comments --- gson/src/main/java/org/baeldung/gson/entities/MyClass.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gson/src/main/java/org/baeldung/gson/entities/MyClass.java b/gson/src/main/java/org/baeldung/gson/entities/MyClass.java index 997f4c3f26..4e717e72c3 100644 --- a/gson/src/main/java/org/baeldung/gson/entities/MyClass.java +++ b/gson/src/main/java/org/baeldung/gson/entities/MyClass.java @@ -29,7 +29,8 @@ public class MyClass { this.name = name; } - @Override public boolean equals(Object o) { + @Override + public boolean equals(Object o) { if (this == o) { return true; } @@ -40,7 +41,8 @@ public class MyClass { return id == myClass.id && Objects.equals(name, myClass.name); } - @Override public int hashCode() { + @Override + public int hashCode() { return Objects.hash(id, name); } From c8ee65b1d2a01ba6a45922c42f26b13daa042709 Mon Sep 17 00:00:00 2001 From: TINO Date: Sat, 9 Mar 2019 15:36:20 +0300 Subject: [PATCH 274/496] BAEL - 1060 --- .../baeldung/rxjava/RxJavaHooksUnitTest.java | 329 ++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java b/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java new file mode 100644 index 0000000000..e31838448b --- /dev/null +++ b/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java @@ -0,0 +1,329 @@ +package com.baeldung.rxjava; + +import org.junit.Test; + +import io.reactivex.Completable; +import io.reactivex.Flowable; +import io.reactivex.Maybe; +import io.reactivex.Observable; +import io.reactivex.Single; +import io.reactivex.flowables.ConnectableFlowable; +import io.reactivex.observables.ConnectableObservable; +import io.reactivex.plugins.RxJavaPlugins; +import io.reactivex.schedulers.Schedulers; + +public class RxJavaHooksUnitTest { + + @Test + public void givenCompletable_whenAssembled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnCompletableAssembly(completable -> { + System.out.println("Assembling Completable"); + return completable; + }); + Completable.fromSingle(Single.just(1)); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenCompletable_whenSubscribed_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnCompletableSubscribe((completable, observer) -> { + System.out.println("Subscribing to Completable"); + return observer; + }); + + Completable.fromSingle(Single.just(1)) + .test(true); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenObservable_whenAssembled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnObservableAssembly(observable -> { + System.out.println("Assembling Observable"); + return observable; + }); + + Observable.range(1, 10); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenObservable_whenSubscribed_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnObservableSubscribe((observable, observer) -> { + System.out.println("Suscribing to Observable"); + return observer; + }); + + Observable.range(1, 10) + .test(true); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenConnectableObservable_whenAssembled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnConnectableObservableAssembly(connectableObservable -> { + System.out.println("Assembling ConnectableObservable"); + return connectableObservable; + }); + + ConnectableObservable.range(1, 10) + .publish() + .connect(); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenFlowable_whenAssembled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnFlowableAssembly(flowable -> { + System.out.println("Assembling Flowable"); + return flowable; + }); + + Flowable.range(1, 10); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenFlowable_whenSubscribed_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnFlowableSubscribe((flowable, observer) -> { + System.out.println("Suscribing to Flowable"); + return observer; + }); + + Flowable.range(1, 10) + .test(); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenConnectableFlowable_whenAssembled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnConnectableFlowableAssembly(connectableFlowable -> { + System.out.println("Assembling ConnectableFlowable"); + return connectableFlowable; + }); + + ConnectableFlowable.range(1, 10) + .publish() + .connect(); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenParallel_whenAssembled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnParallelAssembly(parallelFlowable -> { + System.out.println("Assembling ParallelFlowable"); + return parallelFlowable; + }); + + Flowable.range(1, 10) + .parallel(); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenMaybe_whenAssembled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnMaybeAssembly(maybe -> { + System.out.println("Assembling Maybe"); + return maybe; + }); + + Maybe.just(1); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenMaybe_whenSubscribed_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnMaybeSubscribe((maybe, observer) -> { + System.out.println("Suscribing to Maybe"); + return observer; + }); + + Maybe.just(1) + .test(); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenSingle_whenAssembled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setOnSingleAssembly(single -> { + System.out.println("Assembling Single"); + return single; + }); + + Single.just(1); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenSingle_whenSubscribed_shouldExecuteTheHook() { + + try { + RxJavaPlugins.setOnSingleSubscribe((single, observer) -> { + System.out.println("Suscribing to Single"); + return observer; + }); + + Single.just(1) + .test(); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenAnyScheduler_whenCalled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setScheduleHandler((runnable) -> { + System.out.println("Executing Scheduler"); + return runnable; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.single()) + .test(); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.computation()) + .test(); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenComputationScheduler_whenCalled_shouldExecuteTheHooks() { + try { + RxJavaPlugins.setInitComputationSchedulerHandler((scheduler) -> { + System.out.println("Initializing Computation Scheduler"); + return scheduler.call(); + }); + RxJavaPlugins.setComputationSchedulerHandler((scheduler) -> { + System.out.println("Executing Computation Scheduler"); + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.computation()) + .test(); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenIOScheduler_whenCalled_shouldExecuteTheHooks() { + try { + RxJavaPlugins.setInitIoSchedulerHandler((scheduler) -> { + System.out.println("Initializing IO Scheduler"); + return scheduler.call(); + }); + + RxJavaPlugins.setIoSchedulerHandler((scheduler) -> { + System.out.println("Executing IO Scheduler"); + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.io()) + .test(); + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenNewThreadScheduler_whenCalled_shouldExecuteTheHook() { + try { + RxJavaPlugins.setInitNewThreadSchedulerHandler((scheduler) -> { + System.out.println("Initializing newThread Scheduler"); + return scheduler.call(); + }); + + RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> { + System.out.println("Executing newThread Scheduler"); + return scheduler; + }); + + Observable.range(1, 15) + .map(v -> v * 2) + .subscribeOn(Schedulers.newThread()) + .test(); + + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenSingleScheduler_whenCalled_shouldExecuteTheHooks() { + try { + RxJavaPlugins.setInitSingleSchedulerHandler((scheduler) -> { + System.out.println("Initializing Single Scheduler"); + return scheduler.call(); + }); + + RxJavaPlugins.setSingleSchedulerHandler((scheduler) -> { + System.out.println("Executing Single Scheduler"); + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.single()) + .test(); + + } finally { + RxJavaPlugins.reset(); + } + } + + @Test + public void givenObservable_whenError_shouldExecuteTheHook() { + RxJavaPlugins.setErrorHandler(throwable -> { + System.out.println("Handling error" + throwable.getCause()); + }); + + Observable.error(new IllegalStateException()) + .subscribe(); + } +} From 1f933b8f8fd0d172aa4f0df099d86446955c01a4 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sat, 9 Mar 2019 18:26:45 +0530 Subject: [PATCH 275/496] BAEL-10957 Fix Jhipster Module Tests and Module Renaming -Added hibernate-java8 dependency to fix mapping of Java8 Date, Time types to database types --- jhipster/jhipster-monolithic/pom.xml | 66 ++++++++++++---------------- 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/jhipster/jhipster-monolithic/pom.xml b/jhipster/jhipster-monolithic/pom.xml index 12dead99df..3e98298f56 100644 --- a/jhipster/jhipster-monolithic/pom.xml +++ b/jhipster/jhipster-monolithic/pom.xml @@ -3,7 +3,7 @@ 4.0.0 jhipster-monolithic war - jhipster-monolithic + jhipster-monolithic JHipster Monolithic Application @@ -87,7 +87,7 @@ io.dropwizard.metrics metrics-annotation - + io.dropwizard.metrics metrics-core @@ -95,15 +95,15 @@ io.dropwizard.metrics metrics-json - + io.dropwizard.metrics metrics-jvm - + io.dropwizard.metrics metrics-servlet - + io.dropwizard.metrics metrics-servlets @@ -201,6 +201,10 @@ org.hibernate hibernate-validator + + org.hibernate + hibernate-java8 + org.liquibase liquibase-core @@ -297,8 +301,8 @@ spring-boot:run - + org.eclipse.m2e lifecycle-mapping @@ -340,27 +344,11 @@ - + com.spotify docker-maven-plugin @@ -387,7 +375,8 @@ target/gatling/results src/test/gatling/bodies src/test/gatling/simulations - + true @@ -751,8 +740,9 @@ - cc @@ -868,7 +858,8 @@ - + IDE @@ -930,15 +921,16 @@ S3437,UndocumentedApi,BoldAndItalicTagsCheck - + src/main/webapp/app/**/*.* Web:BoldAndItalicTagsCheck - + src/main/java/**/* squid:S3437 - + src/main/java/**/* squid:UndocumentedApi From 3d5e52cde0a9c876eb38bdd9b5d19dff978f3f43 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sat, 9 Mar 2019 20:08:17 +0530 Subject: [PATCH 276/496] [BAEL-12185] - Removed copied classes from other repositor --- .../deserialization/jacksoninject/Author.java | 26 ------- .../jsonanysetter/Inventory.java | 14 +--- .../deserialization/jsoncreator/Author.java | 27 ------- .../jsondeserialize/Author.java | 24 ------ .../deserialization/jsondeserialize/Book.java | 39 ++++++++-- .../deserialization/jsondeserialize/Item.java | 62 --------------- .../deserialization/jsonsetter/Author.java | 37 --------- .../com/baeldung/jackson/domain/Author.java | 27 ------- .../com/baeldung/jackson/domain/Book.java | 48 ------------ .../com/baeldung/jackson/domain/Course.java | 73 ----------------- .../com/baeldung/jackson/domain/Customer.java | 24 ------ .../baeldung/jackson/domain/Inventory.java | 29 ------- .../com/baeldung/jackson/domain/Item.java | 60 -------------- .../com/baeldung/jackson/domain/Order.java | 50 ------------ .../com/baeldung/jackson/domain/Person.java | 21 +---- .../jackson/inclusion/jsonignore/Author.java | 29 ------- .../jackson/inclusion/jsonignore/Person.java | 48 ------------ .../jsonignoreproperties/Course.java | 78 ------------------- .../jackson/inclusion/jsoninclude/Author.java | 34 -------- .../jackson/miscellaneous/custom/Course.java | 76 ------------------ .../custom/CustomCourseAnnotation.java | 20 ----- .../jackson/miscellaneous/custom/Item.java | 63 --------------- .../jackson/miscellaneous/disable/Author.java | 36 --------- .../jackson/miscellaneous/mixin/Author.java | 30 ------- .../miscellaneous/mixin/IgnoreListMixIn.java | 13 ---- .../jsonanygetter/Inventory.java | 43 ---------- .../serialization/jsongetter/Author.java | 32 -------- .../jsonpropertyorder/Author.java | 31 -------- .../jsonpropertyorder/Person.java | 42 ---------- .../serialization/jsonrawvalue/Customer.java | 28 ------- .../serialization/jsonrootname/Author.java | 32 -------- .../serialization/jsonserialize/Author.java | 29 ------- .../serialization/jsonserialize/Book.java | 52 ------------- .../jsonserialize/CustomDateSerializer.java | 34 -------- .../serialization/jsonserialize/Item.java | 62 --------------- .../serialization/jsonvalue/Course.java | 78 ------------------- .../jacksoninject/JacksonInjectUnitTest.java | 46 ----------- .../jsoncreator/JsonCreatorUnitTest.java | 41 ---------- .../JsonDeserializeUnitTest.java | 2 +- .../jsonsetter/JsonSetterUnitTest.java | 35 --------- .../jackson/general/jsonfilter/Author.java | 32 -------- .../jsonfilter/JsonFilterUnitTest.java | 42 ---------- .../jackson/general/jsonformat/Book.java | 54 ------------- .../jsonformat/JsonFormatUnitTest.java | 63 --------------- .../jackson/general/jsonproperty/Author.java | 29 ------- .../jackson/general/jsonproperty/Book.java | 61 --------------- .../jackson/general/jsonproperty/Item.java | 62 --------------- .../jsonproperty/JsonPropertyUnitTest.java | 70 ----------------- .../jsonignore/JsonIgnoreUnitTest.java | 41 ---------- .../JsonIgnorePropertiesUnitTest.java | 52 ------------- .../jsoninclude/JsonIncludeUnitTest.java | 40 ---------- .../miscellaneous/custom/CustomUnitTest.java | 51 ------------ .../disable/DisableUnitTest.java | 58 -------------- .../miscellaneous/mixin/MixInUnitTest.java | 58 -------------- .../jsonanygetter/JsonAnyGetterUnitTest.java | 49 ------------ .../jsongetter/JsonGetterUnitTest.java | 40 ---------- .../JsonPropertyOrderUnitTest.java | 42 ---------- .../jsonrawvalue/JsonRawValueUnitTest.java | 40 ---------- .../jsonrootname/JsonRootNameUnitTest.java | 46 ----------- .../jsonserialize/JsonSerializeUnitTest.java | 58 -------------- .../jsonvalue/JsonValueUnitTest.java | 27 ------- .../test/JacksonAnnotationUnitTest.java | 27 ------- 62 files changed, 40 insertions(+), 2577 deletions(-) delete mode 100644 jackson/src/main/java/com/baeldung/jackson/deserialization/jacksoninject/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/deserialization/jsoncreator/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Item.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/deserialization/jsonsetter/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/domain/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/domain/Book.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/domain/Course.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/domain/Customer.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/domain/Inventory.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/domain/Item.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/domain/Order.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignore/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignore/Person.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignoreproperties/Course.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/inclusion/jsoninclude/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/Course.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/CustomCourseAnnotation.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/Item.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/miscellaneous/disable/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/IgnoreListMixIn.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonanygetter/Inventory.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsongetter/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonpropertyorder/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonpropertyorder/Person.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonrawvalue/Customer.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonrootname/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Author.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Book.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/CustomDateSerializer.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Item.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/serialization/jsonvalue/Course.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/jacksoninject/JacksonInjectUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/jsoncreator/JsonCreatorUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/jsonsetter/JsonSetterUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonfilter/Author.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonfilter/JsonFilterUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonformat/Book.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonformat/JsonFormatUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Author.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Book.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Item.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/JsonPropertyUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignore/JsonIgnoreUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignoreproperties/JsonIgnorePropertiesUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/inclusion/jsoninclude/JsonIncludeUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/miscellaneous/custom/CustomUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/miscellaneous/disable/DisableUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/miscellaneous/mixin/MixInUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/serialization/jsonanygetter/JsonAnyGetterUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/serialization/jsongetter/JsonGetterUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/serialization/jsonpropertyorder/JsonPropertyOrderUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/serialization/jsonrawvalue/JsonRawValueUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/serialization/jsonrootname/JsonRootNameUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/serialization/jsonserialize/JsonSerializeUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/serialization/jsonvalue/JsonValueUnitTest.java diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/jacksoninject/Author.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/jacksoninject/Author.java deleted file mode 100644 index db8b594509..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/deserialization/jacksoninject/Author.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.jackson.deserialization.jacksoninject; - -import com.baeldung.jackson.domain.Item; - -import java.util.ArrayList; -import java.util.List; - -public class Author extends Person { - - List items = new ArrayList<>(); - - public Author() { - } - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsonanysetter/Inventory.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/jsonanysetter/Inventory.java index c4daf68bd6..d9748e2997 100644 --- a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsonanysetter/Inventory.java +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/jsonanysetter/Inventory.java @@ -1,24 +1,14 @@ package com.baeldung.jackson.deserialization.jsonanysetter; -import com.baeldung.jackson.domain.Author; -import com.baeldung.jackson.domain.Item; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import com.fasterxml.jackson.annotation.JsonIgnore; - import java.util.HashMap; import java.util.Map; +import com.fasterxml.jackson.annotation.JsonAnySetter; + public class Inventory { - private Map stock = new HashMap<>(); - private Map countryDeliveryCost = new HashMap<>(); - @JsonIgnore - public Map getStock() { - return stock; - } - public Map getCountryDeliveryCost() { return countryDeliveryCost; } diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsoncreator/Author.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/jsoncreator/Author.java deleted file mode 100644 index d48c95b255..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsoncreator/Author.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.jackson.deserialization.jsoncreator; - -import com.baeldung.jackson.domain.Person; -import com.baeldung.jackson.domain.Item; -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.ArrayList; -import java.util.List; - -public class Author extends Person { - - List items = new ArrayList<>(); - - @JsonCreator - public Author(@JsonProperty("christianName") String firstName, @JsonProperty("surname") String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Author.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Author.java deleted file mode 100644 index 62e108facb..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Author.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.jackson.deserialization.jsondeserialize; - -import com.baeldung.jackson.domain.Item; -import com.baeldung.jackson.domain.Person; - -import java.util.ArrayList; -import java.util.List; - -public class Author extends Person { - - List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Book.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Book.java index dc0d0ee623..1e411da64e 100644 --- a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Book.java +++ b/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Book.java @@ -1,12 +1,16 @@ package com.baeldung.jackson.deserialization.jsondeserialize; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; - import java.math.BigDecimal; import java.util.Date; +import java.util.UUID; -public class Book extends Item { +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +public class Book { + + private UUID id; + private String title; + private float price; private String ISBN; @JsonDeserialize(using = CustomDateDeserializer.class) @@ -16,8 +20,9 @@ public class Book extends Item { public Book() { } - public Book(String title, Author author) { - super(title, author); + public Book(String title) { + this.id = UUID.randomUUID(); + this.title = title; } public String getISBN() { @@ -43,4 +48,28 @@ public class Book extends Item { public void setPages(BigDecimal pages) { this.pages = pages; } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public float getPrice() { + return price; + } + + public void setPrice(float price) { + this.price = price; + } } diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Item.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Item.java deleted file mode 100644 index fc27a586ac..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsondeserialize/Item.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.baeldung.jackson.deserialization.jsondeserialize; - -import com.baeldung.jackson.domain.Person; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Item { - - private UUID id; - private String title; - private List authors = new ArrayList<>(); - private float price; - - public Item() { - } - - public Item(String title, Author author) { - this.id = UUID.randomUUID(); - this.title = title; - this.authors.add(author); - } - - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public float getPrice() { - return price; - } - - public void setPrice(float price) { - this.price = price; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsonsetter/Author.java b/jackson/src/main/java/com/baeldung/jackson/deserialization/jsonsetter/Author.java deleted file mode 100644 index 3f9ae70a88..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/deserialization/jsonsetter/Author.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.baeldung.jackson.deserialization.jsonsetter; - -import com.baeldung.jackson.domain.Item; -import com.baeldung.jackson.domain.Person; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonSetter; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Author extends Person { - - private List items = new ArrayList<>(); - - public Author() { - } - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - @JsonIgnore - public List getItems() { - return items; - } - - @JsonSetter("publications") - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/domain/Author.java b/jackson/src/main/java/com/baeldung/jackson/domain/Author.java deleted file mode 100644 index 9000c00f21..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/domain/Author.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.jackson.domain; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Author extends Person { - - private List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/domain/Book.java b/jackson/src/main/java/com/baeldung/jackson/domain/Book.java deleted file mode 100644 index a5963e33ba..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/domain/Book.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.jackson.domain; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Book extends Item { - - private String ISBN; - private Date published; - private BigDecimal pages; - - public Book() { - } - - public Book(String title, Author author) { - super(title, author); - } - - public String getISBN() { - return ISBN; - } - - public void setISBN(String ISBN) { - this.ISBN = ISBN; - } - - public Date getPublished() { - return published; - } - - public void setPublished(Date published) { - this.published = published; - } - - public BigDecimal getPages() { - return pages; - } - - public void setPages(BigDecimal pages) { - this.pages = pages; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/domain/Course.java b/jackson/src/main/java/com/baeldung/jackson/domain/Course.java deleted file mode 100644 index 672b0bc250..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/domain/Course.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.jackson.domain; - -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Course extends Item { - - public enum Medium { - CLASSROOM, ONLINE - } - - public enum Level { - BEGINNER("Beginner", 1), INTERMEDIATE("Intermediate", 2), ADVANCED("Advanced", 3); - - private String name; - private int number; - - Level(String name, int number) { - this.name = name; - this.number = number; - } - - public String getName() { - return name; - } - } - - private float duration; - private Medium medium; - private Level level; - private List prerequisite; - - public Course(String title, Author author) { - super(title, author); - } - - public float getDuration() { - return duration; - } - - public void setDuration(float duration) { - this.duration = duration; - } - - public Medium getMedium() { - return medium; - } - - public void setMedium(Medium medium) { - this.medium = medium; - } - - public Level getLevel() { - return level; - } - - public void setLevel(Level level) { - this.level = level; - } - - public List getPrerequisite() { - return prerequisite; - } - - public void setPrerequisite(List prerequisite) { - this.prerequisite = prerequisite; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/domain/Customer.java b/jackson/src/main/java/com/baeldung/jackson/domain/Customer.java deleted file mode 100644 index 1e03ff9a13..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/domain/Customer.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.jackson.domain; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Customer extends Person { - - private String configuration; - - public Customer(String firstName, String lastName) { - super(firstName, lastName); - } - - public String getConfiguration() { - return configuration; - } - - public void setConfiguration(String configuration) { - this.configuration = configuration; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/domain/Inventory.java b/jackson/src/main/java/com/baeldung/jackson/domain/Inventory.java deleted file mode 100644 index 41b7dc51da..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/domain/Inventory.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.jackson.domain; - -import java.util.HashMap; -import java.util.Map; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Inventory { - - private Map stock; - - private Map countryDeliveryCost = new HashMap<>(); - - public Map getStock() { - return stock; - } - - public void setStock(Map stock) { - this.stock = stock; - } - - public Map getCountryDeliveryCost() { - return countryDeliveryCost; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/domain/Item.java b/jackson/src/main/java/com/baeldung/jackson/domain/Item.java deleted file mode 100644 index d9d1350a8e..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/domain/Item.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.baeldung.jackson.domain; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Item { - - private UUID id; - private String title; - private List authors = new ArrayList<>(); - private float price; - - public Item() { - } - - public Item(String title, Author author) { - this.id = UUID.randomUUID(); - this.title = title; - this.authors.add(author); - } - - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public float getPrice() { - return price; - } - - public void setPrice(float price) { - this.price = price; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/domain/Order.java b/jackson/src/main/java/com/baeldung/jackson/domain/Order.java deleted file mode 100644 index 91f87f74df..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/domain/Order.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.baeldung.jackson.domain; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Order { - - private UUID id; - private Type type; - private int internalAudit; - - public static class Type { - public long id; - public String name; - } - - public Order() { - this.id = UUID.randomUUID(); - } - - public Order(Type type) { - this(); - this.type = type; - } - - public Order(int internalAudit) { - this(); - this.type = new Type(); - this.type.id = 20; - this.type.name = "Order"; - this.internalAudit = internalAudit; - } - - public UUID getId() { - return id; - } - - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/domain/Person.java b/jackson/src/main/java/com/baeldung/jackson/domain/Person.java index 785efff755..f11ba41113 100644 --- a/jackson/src/main/java/com/baeldung/jackson/domain/Person.java +++ b/jackson/src/main/java/com/baeldung/jackson/domain/Person.java @@ -1,24 +1,12 @@ package com.baeldung.jackson.domain; -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ public class Person { - private UUID id; private String firstName; private String lastName; - - public Person() { - } - + public Person(String firstName, String lastName) { - this.id = UUID.randomUUID(); + super(); this.firstName = firstName; this.lastName = lastName; } @@ -38,8 +26,5 @@ public class Person { public void setLastName(String lastName) { this.lastName = lastName; } - - public UUID getId() { - return id; - } } + diff --git a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignore/Author.java b/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignore/Author.java deleted file mode 100644 index a7801493bf..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignore/Author.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.jackson.inclusion.jsonignore; - -import com.baeldung.jackson.domain.Item; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Author extends Person { - - private List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignore/Person.java b/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignore/Person.java deleted file mode 100644 index 0037d83148..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignore/Person.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.jackson.inclusion.jsonignore; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Person { - - @JsonIgnore - private UUID id; - private String firstName; - private String lastName; - - public Person() { - } - - public Person(String firstName, String lastName) { - this.id = UUID.randomUUID(); - this.firstName = firstName; - this.lastName = lastName; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public UUID getId() { - return id; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignoreproperties/Course.java b/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignoreproperties/Course.java deleted file mode 100644 index 70b4dd9842..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignoreproperties/Course.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.baeldung.jackson.inclusion.jsonignoreproperties; - -import com.baeldung.jackson.domain.Author; -import com.baeldung.jackson.domain.Item; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonIgnoreProperties({ "medium" }) -public class Course extends Item { - - public enum Medium { - CLASSROOM, ONLINE - } - - public enum Level { - BEGINNER("Beginner", 1), INTERMEDIATE("Intermediate", 2), ADVANCED("Advanced", 3); - - private String name; - private int number; - - Level(String name, int number) { - this.name = name; - this.number = number; - } - - public String getName() { - return name; - } - } - - private float duration; - private Medium medium; - private Level level; - private List prerequisite; - - public Course(String title, Author author) { - super(title, author); - } - - public float getDuration() { - return duration; - } - - public void setDuration(float duration) { - this.duration = duration; - } - - public Medium getMedium() { - return medium; - } - - public void setMedium(Medium medium) { - this.medium = medium; - } - - public Level getLevel() { - return level; - } - - public void setLevel(Level level) { - this.level = level; - } - - public List getPrerequisite() { - return prerequisite; - } - - public void setPrerequisite(List prerequisite) { - this.prerequisite = prerequisite; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsoninclude/Author.java b/jackson/src/main/java/com/baeldung/jackson/inclusion/jsoninclude/Author.java deleted file mode 100644 index 30cb2735c2..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsoninclude/Author.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.jackson.inclusion.jsoninclude; - -import com.baeldung.jackson.domain.Person; -import com.baeldung.jackson.domain.Item; -import com.fasterxml.jackson.annotation.JsonInclude; - -import java.util.ArrayList; -import java.util.List; - -import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonInclude(NON_NULL) -public class Author extends Person { - - private List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/Course.java b/jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/Course.java deleted file mode 100644 index a44492b9f7..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/Course.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.baeldung.jackson.miscellaneous.custom; - -import com.baeldung.jackson.domain.Author; - -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@CustomCourseAnnotation -public class Course extends Item { - - public enum Medium { - CLASSROOM, ONLINE - } - - public enum Level { - BEGINNER("Beginner", 1), INTERMEDIATE("Intermediate", 2), ADVANCED("Advanced", 3); - - private String name; - private int number; - - Level(String name, int number) { - this.name = name; - this.number = number; - } - - public String getName() { - return name; - } - } - - private float duration; - private Medium medium; - private Level level; - private List prerequisite; - - public Course(String title, Author author) { - super(title, author); - } - - public float getDuration() { - return duration; - } - - public void setDuration(float duration) { - this.duration = duration; - } - - public Medium getMedium() { - return medium; - } - - public void setMedium(Medium medium) { - this.medium = medium; - } - - public Level getLevel() { - return level; - } - - public void setLevel(Level level) { - this.level = level; - } - - public List getPrerequisite() { - return prerequisite; - } - - public void setPrerequisite(List prerequisite) { - this.prerequisite = prerequisite; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/CustomCourseAnnotation.java b/jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/CustomCourseAnnotation.java deleted file mode 100644 index d7f72ca6ec..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/CustomCourseAnnotation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.jackson.miscellaneous.custom; - -import com.fasterxml.jackson.annotation.*; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@JacksonAnnotationsInside -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonPropertyOrder({ "title", "price", "id", "duration", "authors", "level" }) -@JsonIgnoreProperties({ "prerequisite" }) -public @interface CustomCourseAnnotation { -} diff --git a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/Item.java b/jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/Item.java deleted file mode 100644 index 6625283dec..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/custom/Item.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.baeldung.jackson.miscellaneous.custom; - -import com.baeldung.jackson.domain.Author; -import com.baeldung.jackson.domain.Person; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Item { - - private UUID id; - private String title; - private List authors = new ArrayList<>(); - private float price; - - public Item() { - } - - public Item(String title, Author author) { - this.id = UUID.randomUUID(); - this.title = title; - this.authors.add(author); - } - - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public float getPrice() { - return price; - } - - public void setPrice(float price) { - this.price = price; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/disable/Author.java b/jackson/src/main/java/com/baeldung/jackson/miscellaneous/disable/Author.java deleted file mode 100644 index 0638e32925..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/disable/Author.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.jackson.miscellaneous.disable; - -import com.baeldung.jackson.domain.Item; -import com.baeldung.jackson.domain.Person; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonPropertyOrder({ "lastName", "items", "firstName", "id" }) -public class Author extends Person { - - @JsonIgnore - private List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/Author.java b/jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/Author.java deleted file mode 100644 index 26e3e4b647..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/Author.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.jackson.miscellaneous.mixin; - -import com.baeldung.jackson.domain.Item; -import com.baeldung.jackson.domain.Person; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Author extends Person { - - private List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/IgnoreListMixIn.java b/jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/IgnoreListMixIn.java deleted file mode 100644 index 418c09c251..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/miscellaneous/mixin/IgnoreListMixIn.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.jackson.miscellaneous.mixin; - -import com.fasterxml.jackson.annotation.JsonIgnoreType; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonIgnoreType -public class IgnoreListMixIn { -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonanygetter/Inventory.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonanygetter/Inventory.java deleted file mode 100644 index 52f586d93b..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonanygetter/Inventory.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.baeldung.jackson.serialization.jsonanygetter; - -import com.baeldung.jackson.domain.Author; -import com.baeldung.jackson.domain.Item; -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonIgnore; - -import java.util.HashMap; -import java.util.Map; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Inventory { - - private String location; - - private Map stock = new HashMap<>(); - - private Map countryDeliveryCost = new HashMap<>(); - - public String getLocation() { - return location; - } - - public void setLocation(String location) { - this.location = location; - } - - @JsonIgnore - public Map getStock() { - return stock; - } - - @JsonAnyGetter - public Map getCountryDeliveryCost() { - return countryDeliveryCost; - } - -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsongetter/Author.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsongetter/Author.java deleted file mode 100644 index 8d89fefce7..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsongetter/Author.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.jackson.serialization.jsongetter; - -import com.baeldung.jackson.domain.Item; -import com.baeldung.jackson.domain.Person; -import com.fasterxml.jackson.annotation.JsonGetter; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Author extends Person { - - List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - @JsonGetter("publications") - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonpropertyorder/Author.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonpropertyorder/Author.java deleted file mode 100644 index dadf893cf9..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonpropertyorder/Author.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.jackson.serialization.jsonpropertyorder; - -import com.baeldung.jackson.domain.Item; -import com.fasterxml.jackson.annotation.JsonPropertyOrder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonPropertyOrder({ "items", "firstName", "lastName", "id" }) -public class Author extends Person { - - List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonpropertyorder/Person.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonpropertyorder/Person.java deleted file mode 100644 index 519e48aada..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonpropertyorder/Person.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.jackson.serialization.jsonpropertyorder; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Person { - - private UUID id; - private String firstName; - private String lastName; - - public Person(String firstName, String lastName) { - this.id = UUID.randomUUID(); - this.firstName = firstName; - this.lastName = lastName; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public UUID getId() { - return id; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrawvalue/Customer.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrawvalue/Customer.java deleted file mode 100644 index f19c5314d2..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrawvalue/Customer.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.jackson.serialization.jsonrawvalue; - -import com.baeldung.jackson.domain.Person; -import com.fasterxml.jackson.annotation.JsonRawValue; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Customer extends Person { - - @JsonRawValue - private String configuration; - - public Customer(String firstName, String lastName) { - super(firstName, lastName); - } - - public String getConfiguration() { - return configuration; - } - - public void setConfiguration(String configuration) { - this.configuration = configuration; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrootname/Author.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrootname/Author.java deleted file mode 100644 index b6dd75da54..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonrootname/Author.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.jackson.serialization.jsonrootname; - -import com.baeldung.jackson.domain.Item; -import com.baeldung.jackson.domain.Person; -import com.fasterxml.jackson.annotation.JsonRootName; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonRootName(value = "writer", namespace = "book") -public class Author extends Person { - - List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Author.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Author.java deleted file mode 100644 index 5a6e90d712..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Author.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.jackson.serialization.jsonserialize; - -import com.baeldung.jackson.domain.Person; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Author extends Person { - - List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Book.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Book.java deleted file mode 100644 index 0ecc4e72ce..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Book.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.jackson.serialization.jsonserialize; - -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Book extends Item { - - private String ISBN; - - @JsonSerialize(using = CustomDateSerializer.class) - private Date published; - private BigDecimal pages; - - public Book() { - } - - public Book(String title, Author author) { - super(title, author); - } - - public String getISBN() { - return ISBN; - } - - public void setISBN(String ISBN) { - this.ISBN = ISBN; - } - - public Date getPublished() { - return published; - } - - public void setPublished(Date published) { - this.published = published; - } - - public BigDecimal getPages() { - return pages; - } - - public void setPages(BigDecimal pages) { - this.pages = pages; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/CustomDateSerializer.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/CustomDateSerializer.java deleted file mode 100644 index 131f4f3695..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/CustomDateSerializer.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.jackson.serialization.jsonserialize; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; - -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class CustomDateSerializer extends StdSerializer { - - private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); - - public CustomDateSerializer() { - this(null); - } - - public CustomDateSerializer(Class t) { - super(t); - } - - @Override - public void serialize(Date value, JsonGenerator gen, SerializerProvider arg2) throws IOException, JsonProcessingException { - gen.writeString(formatter.format(value)); - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Item.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Item.java deleted file mode 100644 index 56cfa85793..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonserialize/Item.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.baeldung.jackson.serialization.jsonserialize; - -import com.baeldung.jackson.domain.Person; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Item { - - private UUID id; - private String title; - private List authors = new ArrayList<>(); - private float price; - - public Item() { - } - - public Item(String title, Author author) { - this.id = UUID.randomUUID(); - this.title = title; - this.authors.add(author); - } - - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public float getPrice() { - return price; - } - - public void setPrice(float price) { - this.price = price; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonvalue/Course.java b/jackson/src/main/java/com/baeldung/jackson/serialization/jsonvalue/Course.java deleted file mode 100644 index a3fdc2d8eb..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/serialization/jsonvalue/Course.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.baeldung.jackson.serialization.jsonvalue; - -import com.baeldung.jackson.domain.Author; -import com.baeldung.jackson.domain.Item; -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Course extends Item { - - public enum Medium { - CLASSROOM, ONLINE - } - - public enum Level { - BEGINNER("Beginner", 1), INTERMEDIATE("Intermediate", 2), ADVANCED("Advanced", 3); - - private String name; - private int number; - - Level(String name, int number) { - this.name = name; - this.number = number; - } - - @JsonValue - public String getName() { - return name; - } - } - - private float duration; - private Medium medium; - private Level level; - private List prerequisite; - - public Course(String title, Author author) { - super(title, author); - } - - public float getDuration() { - return duration; - } - - public void setDuration(float duration) { - this.duration = duration; - } - - public Medium getMedium() { - return medium; - } - - public void setMedium(Medium medium) { - this.medium = medium; - } - - public Level getLevel() { - return level; - } - - public void setLevel(Level level) { - this.level = level; - } - - public List getPrerequisite() { - return prerequisite; - } - - public void setPrerequisite(List prerequisite) { - this.prerequisite = prerequisite; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/jacksoninject/JacksonInjectUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/jacksoninject/JacksonInjectUnitTest.java deleted file mode 100644 index 96dbff6f3c..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/deserialization/jacksoninject/JacksonInjectUnitTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.baeldung.jackson.deserialization.jacksoninject; - -import com.fasterxml.jackson.databind.InjectableValues; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.io.IOException; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JacksonInjectUnitTest { - - @Test - public void whenDeserializingUsingJacksonInject_thenCorrect() throws IOException { - - UUID id = UUID.fromString("9616dc8c-bad3-11e6-a4a6-cec0c932ce01"); - - // arrange - String authorJson = "{\"firstName\": \"Alex\", \"lastName\": \"Theedom\"}"; - - // act - InjectableValues inject = new InjectableValues.Std().addValue(UUID.class, id); - Author author = new ObjectMapper().reader(inject) - .forType(Author.class) - .readValue(authorJson); - - // assert - assertThat(author.getId()).isEqualTo(id); - - /* - { - "firstName": "Alex", - "lastName": "Theedom", - "publications": [] - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsoncreator/JsonCreatorUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/jsoncreator/JsonCreatorUnitTest.java deleted file mode 100644 index cc245dab66..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsoncreator/JsonCreatorUnitTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.jackson.deserialization.jsoncreator; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.io.IOException; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonCreatorUnitTest { - - @Test - public void whenDeserializingUsingJsonCreator_thenCorrect() throws IOException { - - // arrange - String authorJson = "{" + " \"christianName\": \"Alex\"," + " \"surname\": \"Theedom\"" + "}"; - - // act - final Author author = new ObjectMapper().readerFor(Author.class) - .readValue(authorJson); - - // assert - assertThat(from(authorJson).getString("christianName")).isEqualTo(author.getFirstName()); - assertThat(from(authorJson).getString("surname")).isEqualTo(author.getLastName()); - - /* - { - "christianName": "Alex", - "surname": "Theedom" - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsondeserialize/JsonDeserializeUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/jsondeserialize/JsonDeserializeUnitTest.java index 1bcde998d6..a7934d96cf 100644 --- a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsondeserialize/JsonDeserializeUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/jsondeserialize/JsonDeserializeUnitTest.java @@ -21,7 +21,7 @@ public class JsonDeserializeUnitTest { public void whenDeserializingUsingJsonDeserialize_thenCorrect() throws IOException { // arrange - String bookJson = "{\"id\":\"957c43f2-fa2e-42f9-bf75-6e3d5bb6960a\",\"title\":\"Effective Java\",\"authors\":[{\"id\":\"9bcd817d-0141-42e6-8f04-e5aaab0980b6\",\"firstName\":\"Joshua\",\"lastName\":\"Bloch\"}],\"price\":0,\"published\":\"25-12-2017 13:30:25\",\"pages\":null,\"isbn\":null}"; + String bookJson = "{\"id\":\"957c43f2-fa2e-42f9-bf75-6e3d5bb6960a\",\"title\":\"Effective Java\",\"price\":0,\"published\":\"25-12-2017 13:30:25\",\"pages\":null,\"isbn\":null}"; // act Book book = new ObjectMapper().readerFor(Book.class) diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonsetter/JsonSetterUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonsetter/JsonSetterUnitTest.java deleted file mode 100644 index 4379fe376c..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonsetter/JsonSetterUnitTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.baeldung.jackson.deserialization.jsonsetter; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.io.IOException; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonSetterUnitTest { - - @Test - public void whenDeserializingUsingJsonSetter_thenCorrect() throws IOException { - - // arrange - String json = "{\"firstName\":\"Alex\",\"lastName\":\"Theedom\",\"publications\":[{\"title\":\"Professional Java EE Design Patterns\"}]}"; - - // act - Author author = new ObjectMapper().readerFor(Author.class) - .readValue(json); - - // assert - assertThat(from(json).getList("publications") - .size()).isEqualTo(author.getItems() - .size()); - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonfilter/Author.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonfilter/Author.java deleted file mode 100644 index 3d5a9c907c..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonfilter/Author.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.jackson.general.jsonfilter; - -import com.baeldung.jackson.domain.Person; -import com.baeldung.jackson.domain.Item; -import com.fasterxml.jackson.annotation.JsonFilter; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonFilter("authorFilter") -public class Author extends Person { - - private List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonfilter/JsonFilterUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonfilter/JsonFilterUnitTest.java deleted file mode 100644 index 6fcc57faa7..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonfilter/JsonFilterUnitTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.jackson.general.jsonfilter; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ser.FilterProvider; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonFilterUnitTest { - - @Test - public void whenSerializingUsingJsonFilter_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - FilterProvider filters = new SimpleFilterProvider().addFilter("authorFilter", SimpleBeanPropertyFilter.filterOutAllExcept("lastName")); - - // act - String result = new ObjectMapper().writer(filters) - .writeValueAsString(author); - - // assert - assertThat(from(result).getList("items")).isNull(); - - /* - { - "lastName": "Theedom" - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonformat/Book.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonformat/Book.java deleted file mode 100644 index e2eb4aa48a..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonformat/Book.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.baeldung.jackson.general.jsonformat; - -import com.baeldung.jackson.domain.Author; -import com.baeldung.jackson.domain.Item; -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Book extends Item { - - private String ISBN; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy HH:mm:ss") - private Date published; - private BigDecimal pages; - - public Book() { - } - - public Book(String title, Author author) { - super(title, author); - } - - public String getISBN() { - return ISBN; - } - - public void setISBN(String ISBN) { - this.ISBN = ISBN; - } - - public Date getPublished() { - return published; - } - - public void setPublished(Date published) { - this.published = published; - } - - public BigDecimal getPages() { - return pages; - } - - public void setPages(BigDecimal pages) { - this.pages = pages; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonformat/JsonFormatUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonformat/JsonFormatUnitTest.java deleted file mode 100644 index 1fe217cef6..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonformat/JsonFormatUnitTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.baeldung.jackson.general.jsonformat; - -import com.baeldung.jackson.domain.Author; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonFormatUnitTest { - - @Test - public void whenSerializingUsingJsonFormat_thenCorrect() throws JsonProcessingException, ParseException { - - // arrange - SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); - df.setTimeZone(TimeZone.getTimeZone("UTC")); - - String toParse = "20-12-2014 14:30:00"; - Date date = df.parse(toParse); - - Book book = new Book("Design Patterns: Elements of Reusable Object-oriented Software", new Author("The", "GoF")); - book.setPublished(date); - - // act - String result = new ObjectMapper().writeValueAsString(book); - - // assert - assertThat(from(result).getString("published")).isEqualTo(toParse); - - /* - { - "id": "762b39be-fd5b-489e-8688-aeb3b9bbf019", - "title": "Design Patterns: Elements of Reusable Object-oriented Software", - "authors": [ - { - "id": "6941b780-0f54-4259-adcb-85523c8f25f4", - "firstName": "The", - "lastName": "GoF", - "items": [] - } - ], - "price": 0, - "published": "20-12-2014 02:30:00", - "pages": null, - "isbn": null - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Author.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Author.java deleted file mode 100644 index 01552df729..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Author.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.jackson.general.jsonproperty; - -import com.baeldung.jackson.domain.Person; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Author extends Person { - - private List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Book.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Book.java deleted file mode 100644 index 100d9634f5..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Book.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.baeldung.jackson.general.jsonproperty; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Book extends Item { - - private String ISBN; - private Date published; - private BigDecimal pages; - private String binding; - - public Book() { - } - - public Book(String title, Author author) { - super(title, author); - } - - public String getISBN() { - return ISBN; - } - - public void setISBN(String ISBN) { - this.ISBN = ISBN; - } - - public Date getPublished() { - return published; - } - - public void setPublished(Date published) { - this.published = published; - } - - public BigDecimal getPages() { - return pages; - } - - public void setPages(BigDecimal pages) { - this.pages = pages; - } - - @JsonProperty("binding") - public String coverBinding() { - return binding; - } - - @JsonProperty("binding") - public void configureBinding(String binding) { - this.binding = binding; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Item.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Item.java deleted file mode 100644 index d7ee430d51..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/Item.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.baeldung.jackson.general.jsonproperty; - -import com.baeldung.jackson.domain.Person; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Item { - - private UUID id; - private String title; - private List authors = new ArrayList<>(); - private float price; - - public Item() { - } - - public Item(String title, Author author) { - this.id = UUID.randomUUID(); - this.title = title; - this.authors.add(author); - } - - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public float getPrice() { - return price; - } - - public void setPrice(float price) { - this.price = price; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/JsonPropertyUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/JsonPropertyUnitTest.java deleted file mode 100644 index 0b88e7fc47..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonproperty/JsonPropertyUnitTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.baeldung.jackson.general.jsonproperty; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.io.IOException; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonPropertyUnitTest { - - @Test - public void whenSerializingUsingJsonProperty_thenCorrect() throws JsonProcessingException { - - // arrange - Book book = new Book("Design Patterns: Elements of Reusable Object-oriented Software", new Author("The", "GoF")); - book.configureBinding("Hardback"); - - // act - String result = new ObjectMapper().writeValueAsString(book); - - // assert - assertThat(from(result).getString("binding")).isEqualTo("Hardback"); - - /* - { - "id": "cd941587-d1ae-4c2a-9a36-29533bf50411", - "title": "Design Patterns: Elements of Reusable Object-oriented Software", - "authors": [ - { - "id": "c8e26318-2f5b-4fa2-9fdc-6e99be021fca", - "firstName": "The", - "lastName": "GoF", - "items": [] - } - ], - "price": 0, - "published": null, - "pages": null, - "isbn": null, - "binding": "Hardback" - } - */ - - } - - @Test - public void whenDeserializingUsingJsonProperty_thenCorrect() throws IOException { - - // arrange - String result = "{\"id\":\"cd941587-d1ae-4c2a-9a36-29533bf50411\",\"title\":\"Design Patterns: Elements of Reusable Object-oriented Software\",\"authors\":[{\"id\":\"c8e26318-2f5b-4fa2-9fdc-6e99be021fca\",\"firstName\":\"The\",\"lastName\":\"GoF\"}],\"binding\":\"Hardback\"}"; - - // act - Book book = new ObjectMapper().readerFor(Book.class) - .readValue(result); - - // assert - assertThat(book.coverBinding()).isEqualTo("Hardback"); - - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignore/JsonIgnoreUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignore/JsonIgnoreUnitTest.java deleted file mode 100644 index 89e3c15f04..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignore/JsonIgnoreUnitTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.jackson.inclusion.jsonignore; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonIgnoreUnitTest { - - @Test - public void whenSerializingUsingJsonIgnore_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - - // act - String result = new ObjectMapper().writeValueAsString(author); - - // assert - assertThat(from(result).getString("firstName")).isEqualTo("Alex"); - assertThat(from(result).getString("lastName")).isEqualTo("Theedom"); - assertThat(from(result).getString("id")).isNull(); - - /* - { - "firstName": "Alex", - "lastName": "Theedom", - "items": [] - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignoreproperties/JsonIgnorePropertiesUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignoreproperties/JsonIgnorePropertiesUnitTest.java deleted file mode 100644 index be20d242c9..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignoreproperties/JsonIgnorePropertiesUnitTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.jackson.inclusion.jsonignoreproperties; - -import com.baeldung.jackson.domain.Author; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonIgnorePropertiesUnitTest { - - @Test - public void whenSerializingUsingJsonIgnoreProperties_thenCorrect() throws JsonProcessingException { - - // arrange - Course course = new Course("Spring Security", new Author("Eugen", "Paraschiv")); - course.setMedium(Course.Medium.ONLINE); - - // act - String result = new ObjectMapper().writeValueAsString(course); - - // assert - assertThat(from(result).getString("medium")).isNull(); - - /* - { - "id": "ef0c8d2b-b088-409e-905c-95ac88dc0ed0", - "title": "Spring Security", - "authors": [ - { - "id": "47a4f498-b0f3-4daf-909f-d2c35a0fe3c2", - "firstName": "Eugen", - "lastName": "Paraschiv", - "items": [] - } - ], - "price": 0, - "duration": 0, - "level": null, - "prerequisite": null - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsoninclude/JsonIncludeUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/inclusion/jsoninclude/JsonIncludeUnitTest.java deleted file mode 100644 index ca4c4b751a..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsoninclude/JsonIncludeUnitTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.baeldung.jackson.inclusion.jsoninclude; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonIncludeUnitTest { - - @Test - public void whenSerializingUsingJsonInclude_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", null); - - // act - String result = new ObjectMapper().writeValueAsString(author); - - // assert - assertThat(from(result).getString("firstName")).isEqualTo("Alex"); - assertThat(result).doesNotContain("lastName"); - - /* - { - "id": "e8bb4802-6e0c-4fa5-9f68-c233272399cd", - "firstName": "Alex", - "items": [] - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/miscellaneous/custom/CustomUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/miscellaneous/custom/CustomUnitTest.java deleted file mode 100644 index 8f90c02875..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/miscellaneous/custom/CustomUnitTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.jackson.miscellaneous.custom; - -import com.baeldung.jackson.domain.Author; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class CustomUnitTest { - - @Test - public void whenSerializingUsingCustom_thenCorrect() throws JsonProcessingException { - - // arrange - Course course = new Course("Spring Security", new Author("Eugen", "Paraschiv")); - course.setMedium(Course.Medium.ONLINE); - - // act - String result = new ObjectMapper().writeValueAsString(course); - - // assert - assertThat(from(result).getString("title")).isEqualTo("Spring Security"); - - /* - { - "title": "Spring Security", - "price": 0, - "id": "7dfd4db9-1175-432f-a53b-687423f7bb9b", - "duration": 0, - "authors": [ - { - "id": "da0738f6-033c-4974-8d87-92820e5ccf27", - "firstName": "Eugen", - "lastName": "Paraschiv", - "items": [] - } - ], - "medium": "ONLINE" - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/miscellaneous/disable/DisableUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/miscellaneous/disable/DisableUnitTest.java deleted file mode 100644 index f9bc14291e..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/miscellaneous/disable/DisableUnitTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.baeldung.jackson.miscellaneous.disable; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.MapperFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class DisableUnitTest { - - @Test - public void whenSerializingUsingDisable_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - - // act - ObjectMapper mapper = new ObjectMapper(); - String result = mapper.writeValueAsString(author); - - // assert - assertThat(from(result).getList("items")).isNull(); - - /* - { - "lastName": "Theedom", - "firstName": "Alex", - "id": "de4afbb4-b24d-45c8-bb00-fd6b9acb42f1" - } - */ - - // act - mapper = new ObjectMapper(); - mapper.disable(MapperFeature.USE_ANNOTATIONS); - result = mapper.writeValueAsString(author); - - // assert - assertThat(from(result).getList("items")).isNotNull(); - - /* - { - "id": "81e6ed72-6b27-4fe9-a36f-e3171c5b55ef", - "firstName": "Alex", - "lastName": "Theedom", - "items": [] - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/miscellaneous/mixin/MixInUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/miscellaneous/mixin/MixInUnitTest.java deleted file mode 100644 index 732cda58d0..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/miscellaneous/mixin/MixInUnitTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.baeldung.jackson.miscellaneous.mixin; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.util.List; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class MixInUnitTest { - - @Test - public void whenSerializingUsingMixIn_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - - // act - String result = new ObjectMapper().writeValueAsString(author); - - // assert - assertThat(from(result).getList("items")).isNotNull(); - - /* - { - "id": "f848b076-00a4-444a-a50b-328595dd9bf5", - "firstName": "Alex", - "lastName": "Theedom", - "items": [] - } - */ - - ObjectMapper mapper = new ObjectMapper(); - mapper.addMixIn(List.class, IgnoreListMixIn.class); - - result = mapper.writeValueAsString(author); - - // assert - assertThat(from(result).getList("items")).isNull(); - - /* - { - "id": "9ffefb7d-e56f-447c-9009-e92e142f8347", - "firstName": "Alex", - "lastName": "Theedom" - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonanygetter/JsonAnyGetterUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/serialization/jsonanygetter/JsonAnyGetterUnitTest.java deleted file mode 100644 index 7a786e0bd6..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonanygetter/JsonAnyGetterUnitTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.jackson.serialization.jsonanygetter; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.util.Map; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonAnyGetterUnitTest { - - @Test - public void whenSerializingUsingJsonAnyGetter_thenCorrect() throws JsonProcessingException { - - // arrange - Inventory inventory = new Inventory(); - Map countryDeliveryCost = inventory.getCountryDeliveryCost(); - inventory.setLocation("France"); - - countryDeliveryCost.put("USA", 10.00f); - countryDeliveryCost.put("UK", 15.00f); - - // act - String result = new ObjectMapper().writeValueAsString(inventory); - - // assert - assertThat(from(result).getString("location")).isEqualTo("France"); - assertThat(from(result).getFloat("USA")).isEqualTo(10.00f); - assertThat(from(result).getFloat("UK")).isEqualTo(15.00f); - - /* - { - "location": "France", - "USA": 10, - "UK": 15 - } - */ - - } - -} diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/jsongetter/JsonGetterUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/serialization/jsongetter/JsonGetterUnitTest.java deleted file mode 100644 index 4bc9c51e83..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/serialization/jsongetter/JsonGetterUnitTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.baeldung.jackson.serialization.jsongetter; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonGetterUnitTest { - - @Test - public void whenSerializingUsingJsonGetter_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - - // act - String result = new ObjectMapper().writeValueAsString(author); - - // assert - assertThat(from(result).getList("publications")).isNotNull(); - assertThat(from(result).getList("items")).isNull(); - - /* - { - "firstName": "Alex", - "lastName": "Theedom", - "publications": [] - } - */ - - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonpropertyorder/JsonPropertyOrderUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/serialization/jsonpropertyorder/JsonPropertyOrderUnitTest.java deleted file mode 100644 index 77ef85ed73..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonpropertyorder/JsonPropertyOrderUnitTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.jackson.serialization.jsonpropertyorder; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath; -import static org.hamcrest.MatcherAssert.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonPropertyOrderUnitTest { - - @Test - public void whenSerializingUsingJsonPropertyOrder_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - - // act - String result = new ObjectMapper().writeValueAsString(author); - - // assert - assertThat(result, matchesJsonSchemaInClasspath("author-jsonpropertyorder-schema.json")); - - // NOTE: property order is not enforced by the JSON specification. - - /* - { - "items": [], - "firstName": "Alex", - "lastName": "Theedom", - "id": "fd277638-9b6e-49f7-81c1-bc52f165245b" - } - */ - - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonrawvalue/JsonRawValueUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/serialization/jsonrawvalue/JsonRawValueUnitTest.java deleted file mode 100644 index f0f0913aee..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonrawvalue/JsonRawValueUnitTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.baeldung.jackson.serialization.jsonrawvalue; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonRawValueUnitTest { - - @Test - public void whenSerializingUsingJsonRawValue_thenCorrect() throws JsonProcessingException { - - // arrange - String customerConfig = "{\"colour\":\"red\",\"device\":\"mobile\",\"orientation\":\"landscape\"}"; - Customer customer = new Customer("Alex", "Theedom"); - customer.setConfiguration("{\"colour\":\"red\",\"device\":\"mobile\",\"orientation\":\"landscape\"}"); - - // act - String result = new ObjectMapper().writeValueAsString(customer); - - // assert - assertThat(result.contains(customerConfig)); - - /* - { - "firstName": "Alex", - "lastName": "Theedom", - "publications": [] - } - */ - - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonrootname/JsonRootNameUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/serialization/jsonrootname/JsonRootNameUnitTest.java deleted file mode 100644 index cb54e63079..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonrootname/JsonRootNameUnitTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.baeldung.jackson.serialization.jsonrootname; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonRootNameUnitTest { - - @Test - public void whenSerializingUsingJsonRootName_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - - // act - ObjectMapper mapper = new ObjectMapper(); - mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); - String result = mapper.writeValueAsString(author); - - // assert - assertThat(from(result).getString("writer.firstName")).isEqualTo("Alex"); - assertThat(from(result).getString("author.firstName")).isNull(); - - /* - { - "writer": { - "id": "0f50dca6-3dd7-4801-a334-fd1614276389", - "firstName": "Alex", - "lastName": "Theedom", - "items": [] - } - } - */ - - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonserialize/JsonSerializeUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/serialization/jsonserialize/JsonSerializeUnitTest.java deleted file mode 100644 index cca018e78d..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonserialize/JsonSerializeUnitTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.baeldung.jackson.serialization.jsonserialize; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.text.ParseException; -import java.text.SimpleDateFormat; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonSerializeUnitTest { - - @Test - public void whenSerializingUsingJsonSerialize_thenCorrect() throws JsonProcessingException, ParseException { - - // arrange - Author joshuaBloch = new Author("Joshua", "Bloch"); - Book book = new Book("Effective Java", joshuaBloch); - - SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); - String toParse = "25-12-2017 13:30:25"; - book.setPublished(df.parse(toParse)); - - // act - String result = new ObjectMapper().writeValueAsString(book); - - // assert - assertThat(from(result).getString("published")).isEqualTo(toParse); - - /* - { - "id": "957c43f2-fa2e-42f9-bf75-6e3d5bb6960a", - "title": "Effective Java", - "authors": [ - { - "id": "9bcd817d-0141-42e6-8f04-e5aaab0980b6", - "firstName": "Joshua", - "lastName": "Bloch", - "items": [] - } - ], - "price": 0, - "published": "25-12-2017 13:30:25", - "pages": null, - "isbn": null - } - */ - - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonvalue/JsonValueUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/serialization/jsonvalue/JsonValueUnitTest.java deleted file mode 100644 index 465daf13f5..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/serialization/jsonvalue/JsonValueUnitTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.jackson.serialization.jsonvalue; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonValueUnitTest { - - @Test - public void whenSerializingUsingJsonValue_thenCorrect() throws JsonProcessingException { - - // act - String result = new ObjectMapper().writeValueAsString(Course.Level.ADVANCED); - - // assert - assertThat(result).isEqualTo("\"Advanced\""); - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java index c8c4c592f0..52d367f739 100644 --- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java @@ -39,7 +39,6 @@ import com.baeldung.jackson.dtos.withEnum.DistanceEnumWithValue; import com.baeldung.jackson.exception.UserWithRoot; import com.baeldung.jackson.jsonview.Item; import com.baeldung.jackson.jsonview.Views; -import com.baeldung.jackson.serialization.jsonrootname.Author; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.InjectableValues; import com.fasterxml.jackson.databind.MapperFeature; @@ -48,7 +47,6 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; -import com.fasterxml.jackson.dataformat.xml.XmlMapper; public class JacksonAnnotationUnitTest { @@ -388,30 +386,5 @@ public class JacksonAnnotationUnitTest { // assert assertThat(aliasBean.getFirstName(), is("Alex")); } - - @Test - public void whenSerializingUsingXMLRootNameWithNameSpace_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - - // act - ObjectMapper mapper = new XmlMapper(); - mapper = mapper.enable(SerializationFeature.WRAP_ROOT_VALUE).enable(SerializationFeature.INDENT_OUTPUT); - String result = mapper.writeValueAsString(author); - - // assert - assertThat(result, containsString("")); - - /* - - 3006b44a-cf62-4cfe-b3d8-30dc6c46ea96 - Alex - Theedom - - - */ - - } } From 8cf72e2e7ee4e53dcd3a3b240231a5258945ec55 Mon Sep 17 00:00:00 2001 From: mikr Date: Sat, 9 Mar 2019 17:18:23 +0100 Subject: [PATCH 277/496] BAEL-2217 forEach inside forEach in Kotlin: add flatMap example --- .../kotlin/com/baeldung/forEach/forEach.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt b/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt index ef56009c71..20eda4e64f 100644 --- a/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt +++ b/core-kotlin/src/main/kotlin/com/baeldung/forEach/forEach.kt @@ -5,6 +5,15 @@ class Country(val name : String, val cities : List) class City(val name : String, val streets : List) +fun City.getStreetsWithCityName() : List { + return streets.map { "$name, $it" }.toList() +} + +fun Country.getCitiesWithCountryName() : List { + return cities.flatMap { it.getStreetsWithCityName() } + .map { "$name, $it" } +} + class World { private val streetsOfAmsterdam = listOf("Herengracht", "Prinsengracht") @@ -45,6 +54,19 @@ class World { } } } + + fun allStreetsFlatMap() { + + countries.flatMap { it.cities} + .flatMap { it.streets} + .forEach { println(it) } + } + + fun allFlatMapTable() { + + countries.flatMap { it.getCitiesWithCountryName() } + .forEach { println(it) } + } } fun main(args : Array) { @@ -56,6 +78,10 @@ fun main(args : Array) { world.allNested() world.allTable() + + world.allStreetsFlatMap() + + world.allFlatMapTable() } From cf5c99745fee64e00658b7fa034590b9386533ce Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sat, 9 Mar 2019 22:54:08 +0530 Subject: [PATCH 278/496] BAEL-10957 Fix Jhipster Module Tests and Module Renaming -Added hibernate-java8 dependency in jhipster parent project to fix mapping of Java8 Date, Time types to database types and thereby fix all the tests that were failing due to this --- jhipster/jhipster-monolithic/pom.xml | 66 ++++++++++++++++------------ jhipster/pom.xml | 13 ++++-- 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/jhipster/jhipster-monolithic/pom.xml b/jhipster/jhipster-monolithic/pom.xml index 3e98298f56..12dead99df 100644 --- a/jhipster/jhipster-monolithic/pom.xml +++ b/jhipster/jhipster-monolithic/pom.xml @@ -3,7 +3,7 @@ 4.0.0 jhipster-monolithic war - jhipster-monolithic + jhipster-monolithic JHipster Monolithic Application @@ -87,7 +87,7 @@ io.dropwizard.metrics metrics-annotation - + io.dropwizard.metrics metrics-core @@ -95,15 +95,15 @@ io.dropwizard.metrics metrics-json - + io.dropwizard.metrics metrics-jvm - + io.dropwizard.metrics metrics-servlet - + io.dropwizard.metrics metrics-servlets @@ -201,10 +201,6 @@ org.hibernate hibernate-validator - - org.hibernate - hibernate-java8 - org.liquibase liquibase-core @@ -301,8 +297,8 @@ spring-boot:run - + org.eclipse.m2e lifecycle-mapping @@ -344,11 +340,27 @@ - + com.spotify docker-maven-plugin @@ -375,8 +387,7 @@ target/gatling/results src/test/gatling/bodies src/test/gatling/simulations - + true @@ -740,9 +751,8 @@ - cc @@ -858,8 +868,7 @@ - + IDE @@ -921,16 +930,15 @@ S3437,UndocumentedApi,BoldAndItalicTagsCheck - + src/main/webapp/app/**/*.* Web:BoldAndItalicTagsCheck - + src/main/java/**/* squid:S3437 - + src/main/java/**/* squid:UndocumentedApi diff --git a/jhipster/pom.xml b/jhipster/pom.xml index 3fcc53b354..e2a19ab21f 100644 --- a/jhipster/pom.xml +++ b/jhipster/pom.xml @@ -15,10 +15,17 @@ ../parent-boot-1
+ + + org.hibernate + hibernate-java8 + + + jhipster-monolithic jhipster-microservice - jhipster-uaa - - + jhipster-uaa + + From 398770b64f76b0572399b49b0cbed75ecccce861 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sat, 9 Mar 2019 22:58:23 +0530 Subject: [PATCH 279/496] BAEL-10957 Fixed formatting --- jhipster/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jhipster/pom.xml b/jhipster/pom.xml index e2a19ab21f..c50aac0c7a 100644 --- a/jhipster/pom.xml +++ b/jhipster/pom.xml @@ -25,7 +25,7 @@ jhipster-monolithic jhipster-microservice - jhipster-uaa - - + jhipster-uaa + + From 92e54a9231c45696a7d0f7fdd950bb0865133b52 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sat, 9 Mar 2019 23:57:02 +0530 Subject: [PATCH 280/496] [BAEL-12185] - Removed copied classes from other repository - part 2 --- .../inclusion/jsonautodetect/Order.java | 54 -------------- .../inclusion/jsonignoretype/Order.java | 44 ----------- .../baeldung/jackson/polymorphism/Order.java | 62 ---------------- .../jsonanysetter/JsonAnySetterUnitTest.java | 50 ------------- .../JsonDeserializeUnitTest.java | 35 --------- .../general/jsonidentityinfo/Author.java | 31 -------- .../general/jsonidentityinfo/Course.java | 73 ------------------- .../general/jsonidentityinfo/Item.java | 64 ---------------- .../JsonIdentityInfoUnitTest.java | 60 --------------- .../general/jsonidentityinfo/Person.java | 45 ------------ .../jsonunwrapped/JsonUnwrappedUnitTest.java | 43 ----------- .../jackson/general/jsonunwrapped/Order.java | 54 -------------- .../general/jsonview/JsonViewUnitTest.java | 73 ------------------- .../jackson/general/jsonview/Order.java | 57 --------------- .../jackson/general/jsonview/Views.java | 15 ---- .../jackson/general/reference/Author.java | 30 -------- .../jackson/general/reference/Course.java | 73 ------------------- .../jackson/general/reference/Item.java | 64 ---------------- .../jackson/general/reference/Person.java | 45 ------------ .../general/reference/ReferenceUnitTest.java | 59 --------------- .../JsonAutoDetectUnitTest.java | 52 ------------- .../JsonIgnoreTypeUnitTest.java | 40 ---------- .../polymorphism/PolymorphismUnitTest.java | 66 ----------------- 23 files changed, 1189 deletions(-) delete mode 100644 jackson/src/main/java/com/baeldung/jackson/inclusion/jsonautodetect/Order.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignoretype/Order.java delete mode 100644 jackson/src/main/java/com/baeldung/jackson/polymorphism/Order.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/jsonanysetter/JsonAnySetterUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/jsondeserialize/JsonDeserializeUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Author.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Course.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Item.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/JsonIdentityInfoUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Person.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonunwrapped/JsonUnwrappedUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonunwrapped/Order.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonview/JsonViewUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonview/Order.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/jsonview/Views.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/reference/Author.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/reference/Course.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/reference/Item.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/reference/Person.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/general/reference/ReferenceUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/inclusion/jsonautodetect/JsonAutoDetectUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignoretype/JsonIgnoreTypeUnitTest.java delete mode 100644 jackson/src/test/java/com/baeldung/jackson/polymorphism/PolymorphismUnitTest.java diff --git a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonautodetect/Order.java b/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonautodetect/Order.java deleted file mode 100644 index f2ff5eeb08..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonautodetect/Order.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.baeldung.jackson.inclusion.jsonautodetect; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonAutoDetect(fieldVisibility = Visibility.ANY) -public class Order { - - private UUID id; - private Type type; - private int internalAudit; - - public static class Type { - public long id; - public String name; - } - - public Order() { - this.id = UUID.randomUUID(); - } - - public Order(Type type) { - this(); - this.type = type; - } - - public Order(int internalAudit) { - this(); - this.type = new Type(); - this.type.id = 20; - this.type.name = "Order"; - this.internalAudit = internalAudit; - } - - public UUID getId() { - return id; - } - - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignoretype/Order.java b/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignoretype/Order.java deleted file mode 100644 index 0d8867933f..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/inclusion/jsonignoretype/Order.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.jackson.inclusion.jsonignoretype; - -import com.fasterxml.jackson.annotation.JsonIgnoreType; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Order { - - private UUID id; - private Type type; - - @JsonIgnoreType - public static class Type { - public long id; - public String name; - } - - public Order() { - this.id = UUID.randomUUID(); - } - - public Order(Type type) { - this(); - this.type = type; - } - - public UUID getId() { - return id; - } - - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } -} diff --git a/jackson/src/main/java/com/baeldung/jackson/polymorphism/Order.java b/jackson/src/main/java/com/baeldung/jackson/polymorphism/Order.java deleted file mode 100644 index 1813148b2b..0000000000 --- a/jackson/src/main/java/com/baeldung/jackson/polymorphism/Order.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.baeldung.jackson.polymorphism; - -import com.fasterxml.jackson.annotation.JsonSubTypes; -import com.fasterxml.jackson.annotation.JsonTypeInfo; -import com.fasterxml.jackson.annotation.JsonTypeName; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Order { - - private UUID id; - private Type type; - private int internalAudit; - - @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "ordertype") - @JsonSubTypes({ @JsonSubTypes.Type(value = InternalType.class, name = "internal") }) - public static class Type { - public long id; - public String name; - } - - @JsonTypeName("internal") - public static class InternalType extends Type { - public long id; - public String name; - } - - public Order() { - this.id = UUID.randomUUID(); - } - - public Order(Type type) { - this(); - this.type = type; - } - - public Order(int internalAudit) { - this(); - this.type = new Type(); - this.type.id = 20; - this.type.name = "Order"; - this.internalAudit = internalAudit; - } - - public UUID getId() { - return id; - } - - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonanysetter/JsonAnySetterUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonanysetter/JsonAnySetterUnitTest.java deleted file mode 100644 index 2e1f94bc3c..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonanysetter/JsonAnySetterUnitTest.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.baeldung.jackson.deserialization.jsonanysetter; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.io.IOException; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonAnySetterUnitTest { - - @Test - public void whenDeserializingUsingJsonAnySetter_thenCorrect() throws IOException { - - // arrange - String json = "{\"USA\":10.00,\"UK\":15.00,\"China\":23.00,\"Brazil\":12.00,\"France\":8.00,\"Russia\":18.00}"; - - // act - Inventory inventory = new ObjectMapper().readerFor(Inventory.class) - .readValue(json); - - // assert - assertThat(from(json).getMap(".") - .get("USA")).isEqualTo(inventory.getCountryDeliveryCost() - .get("USA")); - assertThat(from(json).getMap(".") - .get("UK")).isEqualTo(inventory.getCountryDeliveryCost() - .get("UK")); - assertThat(from(json).getMap(".") - .get("China")).isEqualTo(inventory.getCountryDeliveryCost() - .get("China")); - assertThat(from(json).getMap(".") - .get("Brazil")).isEqualTo(inventory.getCountryDeliveryCost() - .get("Brazil")); - assertThat(from(json).getMap(".") - .get("France")).isEqualTo(inventory.getCountryDeliveryCost() - .get("France")); - assertThat(from(json).getMap(".") - .get("Russia")).isEqualTo(inventory.getCountryDeliveryCost() - .get("Russia")); - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsondeserialize/JsonDeserializeUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/jsondeserialize/JsonDeserializeUnitTest.java deleted file mode 100644 index a7934d96cf..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsondeserialize/JsonDeserializeUnitTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.baeldung.jackson.deserialization.jsondeserialize; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.io.IOException; -import java.text.SimpleDateFormat; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonDeserializeUnitTest { - - @Test - public void whenDeserializingUsingJsonDeserialize_thenCorrect() throws IOException { - - // arrange - String bookJson = "{\"id\":\"957c43f2-fa2e-42f9-bf75-6e3d5bb6960a\",\"title\":\"Effective Java\",\"price\":0,\"published\":\"25-12-2017 13:30:25\",\"pages\":null,\"isbn\":null}"; - - // act - Book book = new ObjectMapper().readerFor(Book.class) - .readValue(bookJson); - - // assert - SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); - assertThat(from(bookJson).getString("published")).isEqualTo(df.format(book.getPublished())); - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Author.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Author.java deleted file mode 100644 index 1f36b95b2a..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Author.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.jackson.general.jsonidentityinfo; - -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.ObjectIdGenerators; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") -public class Author extends Person { - - private List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Course.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Course.java deleted file mode 100644 index 80dd9c275e..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Course.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.jackson.general.jsonidentityinfo; - -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Course extends Item { - - public enum Medium { - CLASSROOM, ONLINE - } - - public enum Level { - BEGINNER("Beginner", 1), INTERMEDIATE("Intermediate", 2), ADVANCED("Advanced", 3); - - private String name; - private int number; - - Level(String name, int number) { - this.name = name; - this.number = number; - } - - public String getName() { - return name; - } - } - - private float duration; - private Medium medium; - private Level level; - private List prerequisite; - - public Course(String title, Author author) { - super(title, author); - } - - public float getDuration() { - return duration; - } - - public void setDuration(float duration) { - this.duration = duration; - } - - public Medium getMedium() { - return medium; - } - - public void setMedium(Medium medium) { - this.medium = medium; - } - - public Level getLevel() { - return level; - } - - public void setLevel(Level level) { - this.level = level; - } - - public List getPrerequisite() { - return prerequisite; - } - - public void setPrerequisite(List prerequisite) { - this.prerequisite = prerequisite; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Item.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Item.java deleted file mode 100644 index bad6562122..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Item.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.jackson.general.jsonidentityinfo; - -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.fasterxml.jackson.annotation.ObjectIdGenerators; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") -public class Item { - - private UUID id; - private String title; - private List authors = new ArrayList<>(); - private float price; - - public Item() { - } - - public Item(String title, Author author) { - this.id = UUID.randomUUID(); - this.title = title; - this.authors.add(author); - } - - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public float getPrice() { - return price; - } - - public void setPrice(float price) { - this.price = price; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/JsonIdentityInfoUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/JsonIdentityInfoUnitTest.java deleted file mode 100644 index 014f1a8f69..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/JsonIdentityInfoUnitTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.baeldung.jackson.general.jsonidentityinfo; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.util.Collections; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonIdentityInfoUnitTest { - - @Test - public void whenSerializingUsingJsonIdentityInfo_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - - Course course = new Course("Java EE Introduction", author); - author.setItems(Collections.singletonList(course)); - course.setAuthors(Collections.singletonList(author)); - - // act - String result = new ObjectMapper().writeValueAsString(author); - - // assert - assertThat(from(result).getString("items[0].authors")).isNotNull(); - - /* - Authors are included. - { - "id": "1b408bf9-5946-4a14-a112-fde2953a7fe7", - "firstName": "Alex", - "lastName": "Theedom", - "items": [ - { - "id": "5ed30530-f0a5-42eb-b786-be2c655da968", - "title": "Java EE Introduction", - "authors": [ - "1b408bf9-5946-4a14-a112-fde2953a7fe7" - ], - "price": 0, - "duration": 0, - "medium": null, - "level": null, - "prerequisite": null - } - ] - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Person.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Person.java deleted file mode 100644 index ea80814124..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonidentityinfo/Person.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.baeldung.jackson.general.jsonidentityinfo; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Person { - - private UUID id; - private String firstName; - private String lastName; - - public Person() { - } - - public Person(String firstName, String lastName) { - this.id = UUID.randomUUID(); - this.firstName = firstName; - this.lastName = lastName; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public UUID getId() { - return id; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonunwrapped/JsonUnwrappedUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonunwrapped/JsonUnwrappedUnitTest.java deleted file mode 100644 index 5130e037d5..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonunwrapped/JsonUnwrappedUnitTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.baeldung.jackson.general.jsonunwrapped; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonUnwrappedUnitTest { - - @Test - public void whenSerializingUsingJsonUnwrapped_thenCorrect() throws JsonProcessingException { - - // arrange - Order.Type preorderType = new Order.Type(); - preorderType.id = 10; - preorderType.name = "pre-order"; - - Order order = new Order(preorderType); - - // act - String result = new ObjectMapper().writeValueAsString(order); - - // assert - assertThat(from(result).getInt("id")).isEqualTo(10); - assertThat(from(result).getString("name")).isEqualTo("pre-order"); - - /* - { - "id": 10, - "name": "pre-order" - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonunwrapped/Order.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonunwrapped/Order.java deleted file mode 100644 index b1c5b832c3..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonunwrapped/Order.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.baeldung.jackson.general.jsonunwrapped; - -import com.fasterxml.jackson.annotation.JsonUnwrapped; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Order { - - private UUID id; - - @JsonUnwrapped - private Type type; - private int internalAudit; - - public static class Type { - public long id; - public String name; - } - - public Order() { - this.id = UUID.randomUUID(); - } - - public Order(Type type) { - this(); - this.type = type; - } - - public Order(int internalAudit) { - this(); - this.type = new Type(); - this.type.id = 20; - this.type.name = "Order"; - this.internalAudit = internalAudit; - } - - public UUID getId() { - return id; - } - - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonview/JsonViewUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonview/JsonViewUnitTest.java deleted file mode 100644 index ab609008ce..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonview/JsonViewUnitTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.jackson.general.jsonview; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonViewUnitTest { - - @Test - public void whenSerializingUsingJsonView_andInternalView_thenCorrect() throws JsonProcessingException { - - // arrange - Order order = new Order(120); - - // act - String result = new ObjectMapper().writerWithView(Views.Internal.class) - .writeValueAsString(order); - - // assert - assertThat(from(result).getUUID("id")).isNotNull(); - assertThat(from(result).getObject("type", Order.Type.class)).isNotNull(); - assertThat(from(result).getInt("internalAudit")).isEqualTo(120); - - /* - { - "id": "33806388-795b-4812-b90a-60292111bc5c", - "type": { - "id": 20, - "name": "Order" - }, - "internalAudit": 120 - } - */ - - } - - @Test - public void whenSerializingUsingJsonView_andPublicView_thenCorrect() throws JsonProcessingException { - - // arrange - Order order = new Order(120); - - // act - String result = new ObjectMapper().writerWithView(Views.Public.class) - .writeValueAsString(order); - - // assert - assertThat(from(result).getUUID("id")).isNotNull(); - assertThat(from(result).getObject("type", Order.Type.class)).isNotNull(); - assertThat(result).doesNotContain("internalAudit"); - - /* - { - "id": "5184d5fc-e359-4cdf-93fa-4054025bef4e", - "type": { - "id": 20, - "name": "Order" - } - } - */ - - } - -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonview/Order.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonview/Order.java deleted file mode 100644 index 69adf1b59d..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonview/Order.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.baeldung.jackson.general.jsonview; - -import com.fasterxml.jackson.annotation.JsonView; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Order { - - @JsonView(Views.Public.class) - private UUID id; - - @JsonView(Views.Public.class) - private Type type; - - @JsonView(Views.Internal.class) - private int internalAudit; - - public static class Type { - public long id; - public String name; - } - - public Order() { - this.id = UUID.randomUUID(); - } - - public Order(Type type) { - this(); - this.type = type; - } - - public Order(int internalAudit) { - this(); - this.type = new Type(); - this.type.id = 20; - this.type.name = "Order"; - this.internalAudit = internalAudit; - } - - public UUID getId() { - return id; - } - - public Type getType() { - return type; - } - - public void setType(Type type) { - this.type = type; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/jsonview/Views.java b/jackson/src/test/java/com/baeldung/jackson/general/jsonview/Views.java deleted file mode 100644 index b55997554d..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/jsonview/Views.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.jackson.general.jsonview; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Views { - public static class Public { - } - - public static class Internal extends Public { - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/reference/Author.java b/jackson/src/test/java/com/baeldung/jackson/general/reference/Author.java deleted file mode 100644 index 02dd9470d7..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/reference/Author.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.jackson.general.reference; - -import com.fasterxml.jackson.annotation.JsonManagedReference; - -import java.util.ArrayList; -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Author extends Person { - - private List items = new ArrayList<>(); - - public Author(String firstName, String lastName) { - super(firstName, lastName); - } - - @JsonManagedReference - public List getItems() { - return items; - } - - public void setItems(List items) { - this.items = items; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/reference/Course.java b/jackson/src/test/java/com/baeldung/jackson/general/reference/Course.java deleted file mode 100644 index 251d25a517..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/reference/Course.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.jackson.general.reference; - -import java.util.List; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Course extends Item { - - public enum Medium { - CLASSROOM, ONLINE - } - - public enum Level { - BEGINNER("Beginner", 1), INTERMEDIATE("Intermediate", 2), ADVANCED("Advanced", 3); - - private String name; - private int number; - - Level(String name, int number) { - this.name = name; - this.number = number; - } - - public String getName() { - return name; - } - } - - private float duration; - private Medium medium; - private Level level; - private List prerequisite; - - public Course(String title, Author author) { - super(title, author); - } - - public float getDuration() { - return duration; - } - - public void setDuration(float duration) { - this.duration = duration; - } - - public Medium getMedium() { - return medium; - } - - public void setMedium(Medium medium) { - this.medium = medium; - } - - public Level getLevel() { - return level; - } - - public void setLevel(Level level) { - this.level = level; - } - - public List getPrerequisite() { - return prerequisite; - } - - public void setPrerequisite(List prerequisite) { - this.prerequisite = prerequisite; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/reference/Item.java b/jackson/src/test/java/com/baeldung/jackson/general/reference/Item.java deleted file mode 100644 index 5dd66a8ca3..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/reference/Item.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.jackson.general.reference; - -import com.fasterxml.jackson.annotation.JsonBackReference; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Item { - - private UUID id; - private String title; - - @JsonBackReference - private List authors = new ArrayList<>(); - private float price; - - public Item() { - } - - public Item(String title, Author author) { - this.id = UUID.randomUUID(); - this.title = title; - this.authors.add(author); - } - - public UUID getId() { - return id; - } - - public void setId(UUID id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public List getAuthors() { - return authors; - } - - public void setAuthors(List authors) { - this.authors = authors; - } - - public float getPrice() { - return price; - } - - public void setPrice(float price) { - this.price = price; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/reference/Person.java b/jackson/src/test/java/com/baeldung/jackson/general/reference/Person.java deleted file mode 100644 index 95c0b35b8b..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/reference/Person.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.baeldung.jackson.general.reference; - -import java.util.UUID; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class Person { - - private UUID id; - private String firstName; - private String lastName; - - public Person() { - } - - public Person(String firstName, String lastName) { - this.id = UUID.randomUUID(); - this.firstName = firstName; - this.lastName = lastName; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public UUID getId() { - return id; - } -} diff --git a/jackson/src/test/java/com/baeldung/jackson/general/reference/ReferenceUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/general/reference/ReferenceUnitTest.java deleted file mode 100644 index 7a52a69656..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/general/reference/ReferenceUnitTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.baeldung.jackson.general.reference; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.util.Collections; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class ReferenceUnitTest { - - @Test - public void whenSerializingUsingReference_thenCorrect() throws JsonProcessingException { - - // arrange - Author author = new Author("Alex", "Theedom"); - - Course course = new Course("Java EE Introduction", author); - author.setItems(Collections.singletonList(course)); - course.setAuthors(Collections.singletonList(author)); - - // act - String result = new ObjectMapper().writeValueAsString(author); - - // assert - assertThat(from(result).getString("items[0].authors")).isNull(); - - /* - Without references defined it throws StackOverflowError. - Authors excluded. - - { - "id": "9c45d9b3-4888-4c24-8b74-65ef35627cd7", - "firstName": "Alex", - "lastName": "Theedom", - "items": [ - { - "id": "f8309629-d178-4d67-93a4-b513ec4a7f47", - "title": "Java EE Introduction", - "price": 0, - "duration": 0, - "medium": null, - "level": null, - "prerequisite": null - } - ] - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonautodetect/JsonAutoDetectUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonautodetect/JsonAutoDetectUnitTest.java deleted file mode 100644 index a3e29776a9..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonautodetect/JsonAutoDetectUnitTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.jackson.inclusion.jsonautodetect; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonAutoDetectUnitTest { - - @Test - public void whenSerializingUsingJsonAutoDetect_thenCorrect() throws JsonProcessingException { - - // arrange - Order order = new Order(1234567890); - - // act - String result = new ObjectMapper().writeValueAsString(order); - - // assert - assertThat(from(result).getInt("internalAudit")).isEqualTo(1234567890); - - /* - With @JsonAutoDetect - { - "id": "c94774d9-de8f-4244-85d5-624bd3a4567a", - "type": { - "id": 20, - "name": "Order" - }, - "internalAudit": 1234567890 - } - - Without @JsonAutoDetect - { - "id": "c94774d9-de8f-4244-85d5-624bd3a4567a", - "type": { - "id": 20, - "name": "Order" - } - } - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignoretype/JsonIgnoreTypeUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignoretype/JsonIgnoreTypeUnitTest.java deleted file mode 100644 index e8917ff526..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/inclusion/jsonignoretype/JsonIgnoreTypeUnitTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.baeldung.jackson.inclusion.jsonignoretype; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class JsonIgnoreTypeUnitTest { - - @Test - public void whenSerializingUsingJsonIgnoreType_thenCorrect() throws JsonProcessingException { - - // arrange - Order.Type type = new Order.Type(); - type.id = 10; - type.name = "Pre-order"; - - Order order = new Order(type); - - // act - String result = new ObjectMapper().writeValueAsString(order); - - // assert - assertThat(from(result).getString("id")).isNotNull(); - assertThat(from(result).getString("type")).isNull(); - - /* - {"id":"ac2428da-523e-443c-a18a-4ea4d2791fea"} - */ - - } -} \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/polymorphism/PolymorphismUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/polymorphism/PolymorphismUnitTest.java deleted file mode 100644 index e922cf9976..0000000000 --- a/jackson/src/test/java/com/baeldung/jackson/polymorphism/PolymorphismUnitTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.baeldung.jackson.polymorphism; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import java.io.IOException; - -import static io.restassured.path.json.JsonPath.from; -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Source code github.com/readlearncode - * - * @author Alex Theedom www.readlearncode.com - * @version 1.0 - */ -public class PolymorphismUnitTest { - - @Test - public void whenSerializingUsingPolymorphism_thenCorrect() throws JsonProcessingException { - - // arrange - Order.InternalType internalType = new Order.InternalType(); - internalType.id = 250; - internalType.name = "staff"; - - Order order = new Order(internalType); - - // act - String result = new ObjectMapper().writeValueAsString(order); - - // assert - assertThat(from(result).getString("type.ordertype")).isEqualTo("internal"); - - /* - { - "id": "7fc898e3-b4e7-41b0-8ffa-664cf3663f2e", - "type": { - "ordertype": "internal", - "id": 250, - "name": "staff" - } - } - */ - - } - - @Test - public void whenDeserializingPolymorphic_thenCorrect() throws IOException { - - // arrange - String orderJson = "{\"type\":{\"ordertype\":\"internal\",\"id\":100,\"name\":\"directors\"}}"; - - // act - Order order = new ObjectMapper().readerFor(Order.class) - .readValue(orderJson); - - // assert - assertThat(from(orderJson).getString("type.ordertype")).isEqualTo("internal"); - assertThat(((Order.InternalType) order.getType()).name).isEqualTo("directors"); - assertThat(((Order.InternalType) order.getType()).id).isEqualTo(100); - assertThat(order.getType() - .getClass()).isEqualTo(Order.InternalType.class); - } -} \ No newline at end of file From 274c740ecbf5601eaf542f5e378e47e0e1dc3982 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 9 Mar 2019 23:55:58 +0200 Subject: [PATCH 281/496] Update README.md --- algorithms-miscellaneous-1/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/algorithms-miscellaneous-1/README.md b/algorithms-miscellaneous-1/README.md index 7ed805f7c4..ea6d6f379b 100644 --- a/algorithms-miscellaneous-1/README.md +++ b/algorithms-miscellaneous-1/README.md @@ -17,3 +17,4 @@ - [Java Two Pointer Technique](https://www.baeldung.com/java-two-pointer-technique) - [Permutations of an Array in Java](https://www.baeldung.com/java-array-permutations) - [Implementing Simple State Machines with Java Enums](https://www.baeldung.com/java-enum-simple-state-machine) +- [Generate Combinations in Java](https://www.baeldung.com/java-combinations-algorithm) From b9d8a8ab0a8c077dcfd38ecf68e8a7fdbb742a68 Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 9 Mar 2019 23:56:46 +0200 Subject: [PATCH 282/496] Update README.md --- core-groovy/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-groovy/README.md b/core-groovy/README.md index ec2fcfa574..bac91bf028 100644 --- a/core-groovy/README.md +++ b/core-groovy/README.md @@ -8,3 +8,4 @@ - [Types of Strings in Groovy](https://www.baeldung.com/groovy-strings) - [A Quick Guide to Iterating a Map in Groovy](https://www.baeldung.com/groovy-map-iterating) - [An Introduction to Traits in Groovy](https://www.baeldung.com/groovy-traits) +- [Lists in Groovy](https://www.baeldung.com/groovy-lists) From 939a47f464f6b87f33e36fb93282e564064af08b Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 9 Mar 2019 23:57:33 +0200 Subject: [PATCH 283/496] Update README.md --- core-java-collections-list/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-collections-list/README.md b/core-java-collections-list/README.md index c5139074e9..bfe06581c0 100644 --- a/core-java-collections-list/README.md +++ b/core-java-collections-list/README.md @@ -30,3 +30,4 @@ - [Determine If All Elements Are the Same in a Java List](https://www.baeldung.com/java-list-all-equal) - [List of Primitive Integer Values in Java](https://www.baeldung.com/java-list-primitive-int) - [Performance Comparison of Primitive Lists in Java](https://www.baeldung.com/java-list-primitive-performance) +- [Filtering a Java Collection by a List](https://www.baeldung.com/java-filter-collection-by-list) From ef94015a3696aa9dc428de00a7a15654a2267687 Mon Sep 17 00:00:00 2001 From: Ganesh Pagade Date: Sun, 10 Mar 2019 11:24:33 +0530 Subject: [PATCH 284/496] review comments --- .../java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java b/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java index 3bf2afbe4a..5b787f1956 100644 --- a/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java +++ b/gson/src/test/java/org/baeldung/gson/advance/GsonAdvanceUnitTest.java @@ -81,6 +81,7 @@ public class GsonAdvanceUnitTest { assertEquals(2, outList.size()); assertTrue(outList.get(0) instanceof Dog); + assertTrue(outList.get(1) instanceof Cow); } @Test @@ -101,7 +102,7 @@ public class GsonAdvanceUnitTest { Type listOfAnimals = new TypeToken>() {}.getType(); - RuntimeTypeAdapterFactory adapter = RuntimeTypeAdapterFactory.of(Animal.class) + RuntimeTypeAdapterFactory adapter = RuntimeTypeAdapterFactory.of(Animal.class, "type") .registerSubtype(Dog.class) .registerSubtype(Cow.class); @@ -111,5 +112,6 @@ public class GsonAdvanceUnitTest { assertEquals(2, outList.size()); assertTrue(outList.get(0) instanceof Dog); + assertTrue(outList.get(1) instanceof Cow); } } \ No newline at end of file From 7f24cbad71c57d046908431f354cd890059ca3e1 Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 10 Mar 2019 09:41:07 +0200 Subject: [PATCH 285/496] new example for jackson article --- .../exception/UserWithRootNamespace.java | 18 ++++++++++ .../test/JacksonAnnotationUnitTest.java | 33 +++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 jackson/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java diff --git a/jackson/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java b/jackson/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java new file mode 100644 index 0000000000..bf8c85efba --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java @@ -0,0 +1,18 @@ +package com.baeldung.jackson.exception; + +import com.fasterxml.jackson.annotation.JsonRootName; + +@JsonRootName(value = "user", namespace="users") +public class UserWithRootNamespace { + public int id; + public String name; + + public UserWithRootNamespace() { + super(); + } + + public UserWithRootNamespace(final int id, final String name) { + this.id = id; + this.name = name; + } +} diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java index 52d367f739..ee11f8f20e 100644 --- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java +++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java @@ -37,6 +37,7 @@ import com.baeldung.jackson.date.EventWithSerializer; import com.baeldung.jackson.dtos.MyMixInForIgnoreType; import com.baeldung.jackson.dtos.withEnum.DistanceEnumWithValue; import com.baeldung.jackson.exception.UserWithRoot; +import com.baeldung.jackson.exception.UserWithRootNamespace; import com.baeldung.jackson.jsonview.Item; import com.baeldung.jackson.jsonview.Views; import com.fasterxml.jackson.core.JsonProcessingException; @@ -47,6 +48,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; public class JacksonAnnotationUnitTest { @@ -378,13 +380,40 @@ public class JacksonAnnotationUnitTest { public void whenDeserializingUsingJsonAlias_thenCorrect() throws IOException { // arrange - String json = "{\"fName\": \"Alex\", \"lastName\": \"Theedom\"}"; + String json = "{\"fName\": \"John\", \"lastName\": \"Green\"}"; // act AliasBean aliasBean = new ObjectMapper().readerFor(AliasBean.class).readValue(json); // assert - assertThat(aliasBean.getFirstName(), is("Alex")); + assertThat(aliasBean.getFirstName(), is("John")); } + + @Test + public void whenSerializingUsingXMLRootNameWithNameSpace_thenCorrect() throws JsonProcessingException { + + // arrange + UserWithRootNamespace author = new UserWithRootNamespace(1, "John"); + + // act + ObjectMapper mapper = new XmlMapper(); + mapper = mapper.enable(SerializationFeature.WRAP_ROOT_VALUE).enable(SerializationFeature.INDENT_OUTPUT); + String result = mapper.writeValueAsString(author); + + // assert + assertThat(result, containsString("")); + + /* + + 3006b44a-cf62-4cfe-b3d8-30dc6c46ea96 + 1 + John + + + */ + + } + + } From d03c2181eca532c6af7de71a13c29c7fd41669d1 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Sun, 10 Mar 2019 13:27:47 +0400 Subject: [PATCH 286/496] fastutil code --- .../java/com/baeldung/primitives/PrimitiveMaps.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java b/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java index 4ee10997c2..eaa7e308bb 100644 --- a/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java +++ b/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java @@ -4,6 +4,7 @@ import cern.colt.map.AbstractIntDoubleMap; import cern.colt.map.OpenIntDoubleHashMap; import gnu.trove.map.TDoubleIntMap; import gnu.trove.map.hash.TDoubleIntHashMap; +import it.unimi.dsi.fastutil.ints.*; import org.eclipse.collections.api.map.primitive.*; import org.eclipse.collections.impl.factory.primitive.*; @@ -14,6 +15,17 @@ public class PrimitiveMaps { eclipseCollectionsMap(); troveMap(); coltMap(); + fastutilMap(); + } + + private static void fastutilMap() { + Int2BooleanMap int2BooleanMap = new Int2BooleanOpenHashMap(); + int2BooleanMap.put(1, true); + + Int2BooleanSortedMap int2BooleanSorted = Int2BooleanSortedMaps.EMPTY_MAP; + int2BooleanSorted.putIfAbsent(7, true); + int2BooleanSorted.putIfAbsent(1, true); + int2BooleanSorted.putIfAbsent(4, true); } private static void coltMap() { From 1b48e7943c2942feb1d49b8e4a8a352315a62fa4 Mon Sep 17 00:00:00 2001 From: PranayJain Date: Sun, 10 Mar 2019 17:30:20 +0530 Subject: [PATCH 287/496] BAEL-2719: Fixed the changes to load external file --- spring-boot-ops/pom.xml | 23 ++++++++++ .../baeldung/properties/ConfProperties.java | 43 +++++++++++++++++++ .../ExternalPropertyConfigurer.java | 18 ++++++++ .../ExternalPropertyFileLoader.java | 15 ++++--- .../main/resources/external/conf.properties | 4 -- ...rnalPropertyFileLoaderIntegrationTest.java | 27 ++++++++++++ .../ExternalPropertyFileLoaderUnitTest.java | 25 ----------- .../test/resources/external/conf.properties | 3 ++ 8 files changed, 122 insertions(+), 36 deletions(-) create mode 100644 spring-boot-ops/src/main/java/com/baeldung/properties/ConfProperties.java create mode 100644 spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyConfigurer.java delete mode 100644 spring-boot-ops/src/main/resources/external/conf.properties create mode 100644 spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderIntegrationTest.java delete mode 100644 spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderUnitTest.java create mode 100644 spring-boot-ops/src/test/resources/external/conf.properties diff --git a/spring-boot-ops/pom.xml b/spring-boot-ops/pom.xml index 625b2ad188..6c49351820 100644 --- a/spring-boot-ops/pom.xml +++ b/spring-boot-ops/pom.xml @@ -110,6 +110,29 @@ + + org.apache.maven.plugins + maven-failsafe-plugin + 2.18 + + + + integration-tests + + integration-test + verify + + + + + **/ExternalPropertyFileLoaderIntegrationTest.java + + + + + diff --git a/spring-boot-ops/src/main/java/com/baeldung/properties/ConfProperties.java b/spring-boot-ops/src/main/java/com/baeldung/properties/ConfProperties.java new file mode 100644 index 0000000000..0b6041bb06 --- /dev/null +++ b/spring-boot-ops/src/main/java/com/baeldung/properties/ConfProperties.java @@ -0,0 +1,43 @@ +package com.baeldung.properties; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class ConfProperties { + + @Value("${url}") + private String url; + + @Value("${username}") + private String username; + + @Value("${password}") + private String password; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + +} diff --git a/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyConfigurer.java b/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyConfigurer.java new file mode 100644 index 0000000000..67890d717a --- /dev/null +++ b/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyConfigurer.java @@ -0,0 +1,18 @@ +package com.baeldung.properties; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.io.FileSystemResource; + +@Configuration +public class ExternalPropertyConfigurer { + + @Bean + public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer(); + properties.setLocation(new FileSystemResource("src/test/resources/external/conf.properties")); + properties.setIgnoreResourceNotFound(false); + return properties; + } +} \ No newline at end of file diff --git a/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyFileLoader.java b/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyFileLoader.java index 233ddc0195..dc5e14549b 100644 --- a/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyFileLoader.java +++ b/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyFileLoader.java @@ -1,17 +1,18 @@ package com.baeldung.properties; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.env.ConfigurableEnvironment; @SpringBootApplication public class ExternalPropertyFileLoader { + + @Autowired + ConfProperties prop; + public static void main(String[] args) { - ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ExternalPropertyFileLoader.class).properties("spring.config.name:conf", "spring.config.location:file:src/main/resources/external/") - .build() - .run(args); - ConfigurableEnvironment environment = applicationContext.getEnvironment(); - environment.getProperty("username"); + new SpringApplicationBuilder(ExternalPropertyFileLoader.class).build() + .run(args); } + } diff --git a/spring-boot-ops/src/main/resources/external/conf.properties b/spring-boot-ops/src/main/resources/external/conf.properties deleted file mode 100644 index a724b878b4..0000000000 --- a/spring-boot-ops/src/main/resources/external/conf.properties +++ /dev/null @@ -1,4 +0,0 @@ -url=jdbc:postgresql://localhost:5432/ -username=admin -password=root -spring.main.allow-bean-definition-overriding=true diff --git a/spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderIntegrationTest.java b/spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderIntegrationTest.java new file mode 100644 index 0000000000..2001db57d0 --- /dev/null +++ b/spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderIntegrationTest.java @@ -0,0 +1,27 @@ +package com.baeldung.properties; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = ExternalPropertyFileLoader.class) +public class ExternalPropertyFileLoaderIntegrationTest { + + @Autowired + ConfProperties props; + + @Test + public void whenExternalisedPropertiesLoaded_thenReadValues() throws IOException { + assertEquals("jdbc:postgresql://localhost:5432/", props.getUrl()); + assertEquals("admin", props.getUsername()); + assertEquals("root", props.getPassword()); + } + +} diff --git a/spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderUnitTest.java b/spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderUnitTest.java deleted file mode 100644 index 656d8561ec..0000000000 --- a/spring-boot-ops/src/test/java/com/baeldung/properties/ExternalPropertyFileLoaderUnitTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.properties; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -public class ExternalPropertyFileLoaderUnitTest { - - @Test - public void whenExternalisedPropertiesLoaded_thenReadValues() { - ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ExternalPropertyFileLoader.class).properties("spring.config.name:conf", "spring.config.location:file:src/main/resources/external/") - .build() - .run(); - ConfigurableEnvironment environment = applicationContext.getEnvironment(); - Assert.assertEquals(environment.getProperty("url"), "jdbc:postgresql://localhost:5432/"); - Assert.assertEquals(environment.getProperty("username"), "admin"); - Assert.assertEquals(environment.getProperty("password"), "root"); - } - -} diff --git a/spring-boot-ops/src/test/resources/external/conf.properties b/spring-boot-ops/src/test/resources/external/conf.properties new file mode 100644 index 0000000000..da9533fe1f --- /dev/null +++ b/spring-boot-ops/src/test/resources/external/conf.properties @@ -0,0 +1,3 @@ +url=jdbc:postgresql://localhost:5432/ +username=admin +password=root \ No newline at end of file From 9fae5f5a50f3cca4738b8ef0fd1346c8dc2be781 Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Sun, 10 Mar 2019 17:40:04 +0000 Subject: [PATCH 288/496] BAEL-2522 - Comments addressed. --- .../XmlGregorianCalendarConverter.java | 29 ------------------- .../XmlGregorianCalendarConverterTest.java | 14 ++------- 2 files changed, 3 insertions(+), 40 deletions(-) delete mode 100644 java-dates/src/main/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverter.java diff --git a/java-dates/src/main/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverter.java b/java-dates/src/main/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverter.java deleted file mode 100644 index 7f7515ec4b..0000000000 --- a/java-dates/src/main/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverter.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.xmlgregoriancalendar; - -import javax.xml.datatype.DatatypeConfigurationException; -import javax.xml.datatype.DatatypeFactory; -import javax.xml.datatype.XMLGregorianCalendar; -import java.time.LocalDate; - -public class XmlGregorianCalendarConverter { - - public static void main(String[] args) throws DatatypeConfigurationException { - LocalDate localDate = LocalDate.now(); - System.out.println("localdate: " + localDate); - XMLGregorianCalendar xmlGregorianCalendar = fromLocalDate(localDate); - System.out.println("xmlGregorianCalendar: " + xmlGregorianCalendar); - - xmlGregorianCalendar.setTime(1, 1, 30); - System.out.println("xmlGregorianCalendar with time information: " + xmlGregorianCalendar); - LocalDate newLocalDate = fromXMLGregorianCalendar(xmlGregorianCalendar); - System.out.println("newLocalDate: " + newLocalDate); - } - - static XMLGregorianCalendar fromLocalDate(LocalDate localDate) throws DatatypeConfigurationException { - return DatatypeFactory.newInstance().newXMLGregorianCalendar(localDate.toString()); - } - - static LocalDate fromXMLGregorianCalendar(XMLGregorianCalendar xmlGregorianCalendar) { - return LocalDate.of(xmlGregorianCalendar.getYear(), xmlGregorianCalendar.getMonth(), xmlGregorianCalendar.getDay()); - } -} diff --git a/java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java b/java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java index f27c91be7e..7fe1cd36a1 100644 --- a/java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java +++ b/java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java @@ -16,7 +16,7 @@ public class XmlGregorianCalendarConverterTest { @Test public void fromLocalDateToXMLGregorianCalendar() throws DatatypeConfigurationException { LocalDate localDate = LocalDate.of(2017, 4, 25); - XMLGregorianCalendar xmlGregorianCalendar = fromLocalDate(localDate); + XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(localDate.toString()); assertThat(xmlGregorianCalendar.getYear()).isEqualTo(localDate.getYear()); assertThat(xmlGregorianCalendar.getMonth()).isEqualTo(localDate.getMonthValue()); @@ -26,19 +26,11 @@ public class XmlGregorianCalendarConverterTest { @Test public void fromXMLGregorianCalendarToLocalDate() throws DatatypeConfigurationException { XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar("2017-04-25"); - LocalDate localDate = fromXMLGregorianCalendar(xmlGregorianCalendar); + LocalDate localDate = LocalDate.of(xmlGregorianCalendar.getYear(), xmlGregorianCalendar.getMonth(), xmlGregorianCalendar.getDay()); assertThat(localDate.getYear()).isEqualTo(xmlGregorianCalendar.getYear()); assertThat(localDate.getMonthValue()).isEqualTo(xmlGregorianCalendar.getMonth()); assertThat(localDate.getDayOfMonth()).isEqualTo(xmlGregorianCalendar.getDay()); } - - @Test - public void compositionOfFunctionsIsIdentity() throws DatatypeConfigurationException { // Only if we don't consider time - LocalDate localDate = LocalDate.of(2017, 4, 25); - XMLGregorianCalendar xmlGregorianCalendar = fromLocalDate(localDate); - LocalDate resultDate = fromXMLGregorianCalendar(xmlGregorianCalendar); - - assertThat(resultDate).isEqualTo(localDate); - } + } From 84d83fb8ec138e3a4f8b321a74e7dc64aa89543e Mon Sep 17 00:00:00 2001 From: Erhan KARAKAYA Date: Sun, 10 Mar 2019 21:37:48 +0300 Subject: [PATCH 289/496] Changed class names to make them more memorable --- .../sampleabstract/AbstractService.java | 57 ------------------- .../baeldung/sampleabstract/BallService.java | 28 +++++++++ ...FooService.java => BasketballService.java} | 7 +-- .../org/baeldung/sampleabstract/DemoApp.java | 10 ---- .../org/baeldung/sampleabstract/FooBean.java | 12 ---- .../{BarBean.java => LogRepository.java} | 8 +-- .../{FooBarBean.java => RuleRepository.java} | 8 +-- 7 files changed, 39 insertions(+), 91 deletions(-) delete mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/AbstractService.java create mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/BallService.java rename spring-all/src/main/java/org/baeldung/sampleabstract/{FooService.java => BasketballService.java} (56%) delete mode 100644 spring-all/src/main/java/org/baeldung/sampleabstract/FooBean.java rename spring-all/src/main/java/org/baeldung/sampleabstract/{BarBean.java => LogRepository.java} (50%) rename spring-all/src/main/java/org/baeldung/sampleabstract/{FooBarBean.java => RuleRepository.java} (50%) diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractService.java deleted file mode 100644 index 51882f20b3..0000000000 --- a/spring-all/src/main/java/org/baeldung/sampleabstract/AbstractService.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.baeldung.sampleabstract; - -import org.springframework.beans.factory.annotation.Autowired; - - -public abstract class AbstractService { - - @Autowired - private FooBean fooBean; - - private BarBean barBean; - - private FooBarBean fooBarBean; - - public AbstractService(FooBarBean fooBarBean) { - - this.fooBarBean = fooBarBean; - } - - public FooBean getFooBean() { - - return fooBean; - } - - public void setFooBean(FooBean fooBean) { - - this.fooBean = fooBean; - } - - public BarBean getBarBean() { - - return barBean; - } - - @Autowired - public void setBarBean(BarBean barBean) { - - this.barBean = barBean; - } - - public FooBarBean getFooBarBean() { - - return fooBarBean; - } - - public void setFooBarBean(FooBarBean fooBarBean) { - - this.fooBarBean = fooBarBean; - } - - public void afterInitialize() { - - System.out.println(fooBean.value()); - System.out.println(barBean.value()); - System.out.println(fooBarBean.value()); - } -} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/BallService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/BallService.java new file mode 100644 index 0000000000..9a75de7fa1 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/BallService.java @@ -0,0 +1,28 @@ +package org.baeldung.sampleabstract; + +import org.springframework.beans.factory.annotation.Autowired; + +import javax.annotation.PostConstruct; + +public abstract class BallService { + + private RuleRepository ruleRepository; + + private LogRepository logRepository; + + public BallService(RuleRepository ruleRepository) { + this.ruleRepository = ruleRepository; + } + + @Autowired + public final void setLogRepository(LogRepository logRepository) { + this.logRepository = logRepository; + } + + @PostConstruct + public void afterInitialize() { + + System.out.println(ruleRepository.toString()); + System.out.println(logRepository.toString()); + } +} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/FooService.java b/spring-all/src/main/java/org/baeldung/sampleabstract/BasketballService.java similarity index 56% rename from spring-all/src/main/java/org/baeldung/sampleabstract/FooService.java rename to spring-all/src/main/java/org/baeldung/sampleabstract/BasketballService.java index 8bc625e098..c117231d3c 100644 --- a/spring-all/src/main/java/org/baeldung/sampleabstract/FooService.java +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/BasketballService.java @@ -4,11 +4,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component -public class FooService extends AbstractService { +public class BasketballService extends BallService { @Autowired - public FooService(FooBarBean fooBarBean) { - - super(fooBarBean); + public BasketballService(RuleRepository ruleRepository) { + super(ruleRepository); } } diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java b/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java index 0c3c4ea083..615d354ecf 100644 --- a/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/DemoApp.java @@ -1,28 +1,18 @@ package org.baeldung.sampleabstract; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import javax.annotation.PostConstruct; - @Configuration @ComponentScan(basePackages = "org.baeldung.sampleabstract") public class DemoApp { - @Autowired - private FooService fooService; public static void main(String[] args) { ApplicationContext applicationContext = new AnnotationConfigApplicationContext(DemoApp.class); } - @PostConstruct - public void afterInitialize() { - - fooService.afterInitialize(); - } } diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/FooBean.java b/spring-all/src/main/java/org/baeldung/sampleabstract/FooBean.java deleted file mode 100644 index 5ef623b5af..0000000000 --- a/spring-all/src/main/java/org/baeldung/sampleabstract/FooBean.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.baeldung.sampleabstract; - -import org.springframework.stereotype.Component; - -@Component -public class FooBean { - - public String value() { - - return "fooBean"; - } -} diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/BarBean.java b/spring-all/src/main/java/org/baeldung/sampleabstract/LogRepository.java similarity index 50% rename from spring-all/src/main/java/org/baeldung/sampleabstract/BarBean.java rename to spring-all/src/main/java/org/baeldung/sampleabstract/LogRepository.java index 8aeb5d2001..3a65671493 100644 --- a/spring-all/src/main/java/org/baeldung/sampleabstract/BarBean.java +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/LogRepository.java @@ -3,10 +3,10 @@ package org.baeldung.sampleabstract; import org.springframework.stereotype.Component; @Component -public class BarBean { +public class LogRepository { - public String value() { - - return "barBean"; + @Override + public String toString() { + return "logRepository"; } } diff --git a/spring-all/src/main/java/org/baeldung/sampleabstract/FooBarBean.java b/spring-all/src/main/java/org/baeldung/sampleabstract/RuleRepository.java similarity index 50% rename from spring-all/src/main/java/org/baeldung/sampleabstract/FooBarBean.java rename to spring-all/src/main/java/org/baeldung/sampleabstract/RuleRepository.java index 0f46518a41..fd42178ab6 100644 --- a/spring-all/src/main/java/org/baeldung/sampleabstract/FooBarBean.java +++ b/spring-all/src/main/java/org/baeldung/sampleabstract/RuleRepository.java @@ -3,10 +3,10 @@ package org.baeldung.sampleabstract; import org.springframework.stereotype.Component; @Component -public class FooBarBean { +public class RuleRepository { - public String value() { - - return "fooBarBean"; + @Override + public String toString() { + return "ruleRepository"; } } From d36107b8c0bc1d86445d15500c3de27ed4d836bb Mon Sep 17 00:00:00 2001 From: amit2103 Date: Mon, 11 Mar 2019 00:44:59 +0530 Subject: [PATCH 290/496] [BAEL-10128] Updated spring JPA article --- persistence-modules/spring-jpa/pom.xml | 8 ++++---- .../java/com/baeldung/SpringContextIntegrationTest.java | 2 ++ .../persistence/repository/InMemoryDBIntegrationTest.java | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/persistence-modules/spring-jpa/pom.xml b/persistence-modules/spring-jpa/pom.xml index 29a6996791..3daba6cd55 100644 --- a/persistence-modules/spring-jpa/pom.xml +++ b/persistence-modules/spring-jpa/pom.xml @@ -156,13 +156,13 @@ - 4.3.8.RELEASE + 5.1.5.RELEASE 3.21.0-GA - 5.2.10.Final + 5.2.17.Final 6.0.6 - 1.11.3.RELEASE + 2.1.5.RELEASE 1.4.195 @@ -170,7 +170,7 @@ 2.5 - 5.4.1.Final + 6.0.15.Final 1.4.01 2.2.5 diff --git a/persistence-modules/spring-jpa/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/com/baeldung/SpringContextIntegrationTest.java index aa85128628..822cbb8ed5 100644 --- a/persistence-modules/spring-jpa/src/test/java/com/baeldung/SpringContextIntegrationTest.java +++ b/persistence-modules/spring-jpa/src/test/java/com/baeldung/SpringContextIntegrationTest.java @@ -3,6 +3,7 @@ package com.baeldung; import org.baeldung.config.PersistenceJPAConfigL2Cache; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; @@ -11,6 +12,7 @@ import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { PersistenceJPAConfigL2Cache.class }, loader = AnnotationConfigContextLoader.class) @WebAppConfiguration +@DirtiesContext public class SpringContextIntegrationTest { @Test diff --git a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java index 9ddc48460a..4d1bcbe1b2 100644 --- a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java +++ b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java @@ -35,7 +35,7 @@ public class InMemoryDBIntegrationTest { Student student = new Student(ID, NAME); studentRepository.save(student); - Student student2 = studentRepository.findOne(ID); + Student student2 = studentRepository.findById(ID).get(); assertEquals("name incorrect", NAME, student2.getName()); } From e7bbe5b8adb3af4436b2fb2777c0819e58161f40 Mon Sep 17 00:00:00 2001 From: caroline Date: Sun, 10 Mar 2019 22:24:59 +0100 Subject: [PATCH 291/496] Code changes due to BAEL-2460. Could not put them in spring-cloud-kubernetes because had to use different versions of artifacts. --- spring-cloud/pom.xml | 1 + .../client-service/.gitignore | 24 +++++ .../client-service/Dockerfile | 5 + .../client-service/client-config.yaml | 8 ++ .../client-service-deployment.yaml | 33 ++++++ .../client-service/pom.xml | 96 +++++++++++++++++ .../cloud/kubernetes/client/Application.java | 28 +++++ .../cloud/kubernetes/client/ClientConfig.java | 19 ++++ .../kubernetes/client/ClientController.java | 57 ++++++++++ .../client/RibbonConfiguration.java | 55 ++++++++++ .../client/TravelAgencyService.java | 27 +++++ .../src/main/resources/application.yaml | 16 +++ .../src/main/resources/logback.xml | 13 +++ .../SpringContextIntegrationTest.java | 18 ++++ .../deployment-all.sh | 34 ++++++ .../mongo-deployment.yaml | 45 ++++++++ .../spring-cloud-kubernetes-2/pom.xml | 32 ++++++ .../spring-cloud-kubernetes-2/secret.yaml | 7 ++ .../travel-agency-service/Dockerfile | 5 + .../travel-agency-service/pom.xml | 76 +++++++++++++ .../kubernetes/travelagency/Application.java | 23 ++++ .../controller/TravelAgencyController.java | 46 ++++++++ .../travelagency/model/TravelDeal.java | 100 ++++++++++++++++++ .../repository/TravelDealRepository.java | 13 +++ .../src/main/resources/application.properties | 14 +++ .../src/main/resources/logback-spring.xml | 17 +++ .../src/main/resources/logback.xml | 13 +++ .../travel-agency-config.yaml | 8 ++ .../travel-agency-deployment.yaml | 44 ++++++++ 29 files changed, 877 insertions(+) create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/.gitignore create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/Dockerfile create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/client-config.yaml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/client-service-deployment.yaml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java create mode 100755 spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java create mode 100755 spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/application.yaml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/logback.xml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java create mode 100755 spring-cloud/spring-cloud-kubernetes-2/deployment-all.sh create mode 100644 spring-cloud/spring-cloud-kubernetes-2/mongo-deployment.yaml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/pom.xml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/secret.yaml create mode 100755 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/Dockerfile create mode 100755 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/pom.xml create mode 100755 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java create mode 100644 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java create mode 100644 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java create mode 100644 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java create mode 100644 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/application.properties create mode 100644 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback-spring.xml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback.xml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-config.yaml create mode 100644 spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-deployment.yaml diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index baf86a4386..bf70e0284c 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -32,6 +32,7 @@ spring-cloud-zuul-eureka-integration spring-cloud-contract spring-cloud-kubernetes + spring-cloud-kubernetes-2 spring-cloud-archaius spring-cloud-functions spring-cloud-vault diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/.gitignore b/spring-cloud/spring-cloud-kubernetes-2/client-service/.gitignore new file mode 100644 index 0000000000..2af7cefb0a --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/.gitignore @@ -0,0 +1,24 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes-2/client-service/Dockerfile new file mode 100644 index 0000000000..bd8cf2918f --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/Dockerfile @@ -0,0 +1,5 @@ +FROM openjdk:8-jdk-alpine +VOLUME /tmp +COPY target/client-service-1.0-SNAPSHOT.jar app.jar +ENV JAVA_OPTS="" +ENTRYPOINT exec java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9999 -jar /app.jar \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/client-config.yaml b/spring-cloud/spring-cloud-kubernetes-2/client-service/client-config.yaml new file mode 100644 index 0000000000..329c01582e --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/client-config.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: client-service +data: + application.properties: |- + bean.message=Testing reload ! Message from backend is: %s
Services : %s + diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/client-service-deployment.yaml b/spring-cloud/spring-cloud-kubernetes-2/client-service/client-service-deployment.yaml new file mode 100644 index 0000000000..8867aecc33 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/client-service-deployment.yaml @@ -0,0 +1,33 @@ +kind: Service +apiVersion: v1 +metadata: + name: client-service +spec: + selector: + app: client-service + ports: + - protocol: TCP + port: 8080 + nodePort: 30083 + type: NodePort +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: client-service +spec: + selector: + matchLabels: + app: client-service + replicas: 1 + template: + metadata: + labels: + app: client-service + spec: + containers: + - name: client-service + image: client-service:latest + imagePullPolicy: Never + ports: + - containerPort: 8080 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml b/spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml new file mode 100644 index 0000000000..522013849b --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + client-service + client-service + 1.0-SNAPSHOT + + + com.baeldung.spring.cloud + spring-cloud-kubernetes-2 + 1.0-SNAPSHOT + + + + 1.8 + Finchley.SR2 + 1.0.0.RELEASE + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + org.springframework.cloud + spring-cloud-kubernetes-dependencies + ${spring.cloud.k8s.version} + pom + import + + + + + + + org.springframework.cloud + spring-cloud-kubernetes-discovery + + + org.springframework.cloud + spring-cloud-starter-kubernetes-config + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.cloud + spring-cloud-starter-netflix-hystrix + + + org.springframework.cloud + spring-cloud-starter-kubernetes-ribbon + + + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.spring.cloud.kubernetes.client.Application + JAR + + + + + repackage + + + + + + + + diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java new file mode 100644 index 0000000000..de1f1ec878 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java @@ -0,0 +1,28 @@ +package com.baeldung.spring.cloud.kubernetes.client; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.cloud.netflix.ribbon.RibbonClient; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + + +@SpringBootApplication +@EnableDiscoveryClient +@EnableCircuitBreaker +@RibbonClient(name = "travel-agency-service", configuration = RibbonConfiguration.class) +public class Application { + + @LoadBalanced + @Bean + RestTemplate restTemplate(){ + return new RestTemplate(); + } + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java new file mode 100644 index 0000000000..1158f3c2d2 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java @@ -0,0 +1,19 @@ +package com.baeldung.spring.cloud.kubernetes.client; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "bean") +public class ClientConfig { + + private String message = "Message from backend is: %s
Services : %s"; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java new file mode 100755 index 0000000000..44f412c31d --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java @@ -0,0 +1,57 @@ +package com.baeldung.spring.cloud.kubernetes.client; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.http.ResponseEntity; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +import java.net.UnknownHostException; +import java.util.List; + +@RestController +public class ClientController { + + @Autowired + private DiscoveryClient discoveryClient; + + @Autowired + private ClientConfig config; + + @Autowired + private TravelAgencyService travelAgencyService; + + @RequestMapping("/deals") + public String getDeals() { + return travelAgencyService.getDeals(); + } + + @GetMapping + public String load() throws UnknownHostException { + + RestTemplate restTemplate = new RestTemplate(); + String resourceUrl + = "http://travel-agency-service:8080"; + ResponseEntity response + = restTemplate.getForEntity(resourceUrl, String.class); + + String serviceList = ""; + if (discoveryClient != null) { + List services = this.discoveryClient.getServices(); + + for (String service : services) { + + List instances = this.discoveryClient + .getInstances(service); + + serviceList += ("[" + service + " : " + ((!CollectionUtils.isEmpty(instances))?instances.size():0)+ " instances ]"); + } + } + + return String.format(config.getMessage(), response.getBody(),serviceList); + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java new file mode 100755 index 0000000000..a372e9357f --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 to the original authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.baeldung.spring.cloud.kubernetes.client; + +import com.netflix.client.config.IClientConfig; +import com.netflix.loadbalancer.AvailabilityFilteringRule; +import com.netflix.loadbalancer.IPing; +import com.netflix.loadbalancer.IRule; +import com.netflix.loadbalancer.PingUrl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; + +public class RibbonConfiguration { + + @Autowired + IClientConfig ribbonClientConfig; + + /** + * PingUrl will ping a URL to check the status of each server. + * Say Hello has, as you’ll recall, a method mapped to the /path; that means that Ribbon will get an HTTP 200 response when it pings a running Backend Server + * + * @param config Client configuration + * @return The URL to be used for the Ping + */ + @Bean + public IPing ribbonPing(IClientConfig config) { + return new PingUrl(); + } + + /** + * AvailabilityFilteringRule will use Ribbon’s built-in circuit breaker functionality to filter out any servers in an “open-circuit” state: + * if a ping fails to connect to a given server, or if it gets a read failure for the server, Ribbon will consider that server “dead” until it begins to respond normally. + * + * @param config Client configuration + * @return The Load Balancer rule + */ + @Bean + public IRule ribbonRule(IClientConfig config) { + return new AvailabilityFilteringRule(); + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java new file mode 100644 index 0000000000..792699696e --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.cloud.kubernetes.client; + +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; +import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +public class TravelAgencyService { + + private final RestTemplate restTemplate; + + public TravelAgencyService(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + @HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = { + @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") + }) + public String getDeals() { + return this.restTemplate.getForObject("http://travel-agency-service:8080/deals", String.class); + } + + private String getFallbackName() { + return "Fallback"; + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/application.yaml b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/application.yaml new file mode 100644 index 0000000000..f966fdd7a5 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/application.yaml @@ -0,0 +1,16 @@ +spring: + application.name: client-service + cloud.kubernetes.reload.enabled: true +server.port: 8080 +management: + endpoint: + restart: + enabled: true + health: + enabled: true + info: + enabled: true +ribbon: + http: + client: + enabled: true \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/logback.xml b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java new file mode 100644 index 0000000000..9dc2e4f714 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -0,0 +1,18 @@ +package org.baeldung; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.spring.cloud.kubernetes.client.Application; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +public class SpringContextIntegrationTest { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-cloud/spring-cloud-kubernetes-2/deployment-all.sh b/spring-cloud/spring-cloud-kubernetes-2/deployment-all.sh new file mode 100755 index 0000000000..9c088b7422 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/deployment-all.sh @@ -0,0 +1,34 @@ +### build the repository +mvn clean install + +### set docker env +eval $(minikube docker-env) + +### build the docker images on minikube +cd travel-agency-service +docker build -t travel-agency-service . +cd ../client-service +docker build -t client-service . +cd .. + +### secret and mongodb +kubectl delete -f secret.yaml +kubectl delete -f mongo-deployment.yaml + +kubectl create -f secret.yaml +kubectl create -f mongo-deployment.yaml + +### travel-agency-service +kubectl delete -f travel-agency-service/travel-agency-deployment.yaml +kubectl create -f travel-agency-service/travel-agency-deployment.yaml + + +### client-service +kubectl delete configmap client-service +kubectl delete -f client-service/client-service-deployment.yaml + +kubectl create -f client-service/client-config.yaml +kubectl create -f client-service/client-service-deployment.yaml + +# Check that the pods are running +kubectl get pods \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/mongo-deployment.yaml b/spring-cloud/spring-cloud-kubernetes-2/mongo-deployment.yaml new file mode 100644 index 0000000000..3d40581578 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/mongo-deployment.yaml @@ -0,0 +1,45 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: mongo + name: mongodb-service +spec: + type: NodePort + ports: + - name: "http" + port: 27017 + protocol: TCP + targetPort: 27017 + selector: + service: mongo +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: mongo +spec: + replicas: 1 + template: + metadata: + labels: + service: mongo + name: mongodb-service + spec: + containers: + - args: + - mongod + - --smallfiles + image: mongo:latest + name: mongo + env: + - name: MONGO_INITDB_ROOT_USERNAME + valueFrom: + secretKeyRef: + name: db-secret + key: username + - name: MONGO_INITDB_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: db-secret + key: password diff --git a/spring-cloud/spring-cloud-kubernetes-2/pom.xml b/spring-cloud/spring-cloud-kubernetes-2/pom.xml new file mode 100644 index 0000000000..1ce18a7498 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/pom.xml @@ -0,0 +1,32 @@ + + + 4.0.0 + com.baeldung.spring.cloud + spring-cloud-kubernetes-2 + 1.0-SNAPSHOT + spring-cloud-kubernetes-2 + pom + + + 2.0.6.RELEASE + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + client-service + travel-agency-service + + + diff --git a/spring-cloud/spring-cloud-kubernetes-2/secret.yaml b/spring-cloud/spring-cloud-kubernetes-2/secret.yaml new file mode 100644 index 0000000000..a813c35be7 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/secret.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: db-secret +data: + username: dXNlcg== + password: cDQ1NXcwcmQ= diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/Dockerfile new file mode 100755 index 0000000000..30b66d5eff --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/Dockerfile @@ -0,0 +1,5 @@ +FROM openjdk:8-jdk-alpine +VOLUME /tmp +COPY target/travel-agency-service-1.0-SNAPSHOT.jar app.jar +ENV JAVA_OPTS="" +ENTRYPOINT exec java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9999 -jar /app.jar \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/pom.xml b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/pom.xml new file mode 100755 index 0000000000..a375264533 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + travel-agency-service + 1.0-SNAPSHOT + + + com.baeldung.spring.cloud + spring-cloud-kubernetes-2 + 1.0-SNAPSHOT + + + + 1.8 + Finchley.SR2 + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} + pom + import + + + ch.qos.logback + logback-classic + 1.2.3 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-actuator + + + org.springframework.boot + spring-boot-actuator-autoconfigure + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.spring.cloud.kubernetes.travelagency.Application + JAR + + + + + repackage + + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java new file mode 100755 index 0000000000..f84303a5c8 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java @@ -0,0 +1,23 @@ +package com.baeldung.spring.cloud.kubernetes.travelagency; + +import com.baeldung.spring.cloud.kubernetes.travelagency.controller.TravelAgencyController; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application implements CommandLineRunner { + + private static final Log log = LogFactory.getLog(TravelAgencyController.class); + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + public void run(String... args) throws Exception { + log.info("Travel Agency Started! "); + } + +} diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java new file mode 100644 index 0000000000..55a06dee77 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java @@ -0,0 +1,46 @@ +package com.baeldung.spring.cloud.kubernetes.travelagency.controller; + +import com.baeldung.spring.cloud.kubernetes.travelagency.model.TravelDeal; +import com.baeldung.spring.cloud.kubernetes.travelagency.repository.TravelDealRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.List; +import java.util.Random; +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +@RestController +public class TravelAgencyController { + + @Autowired + private TravelDealRepository travelDealRepository; + + private static final Log log = LogFactory.getLog(TravelAgencyController.class); + + @RequestMapping(method = GET, path = "/deals") + public String deals() { + log.info("Client is requesting new deals!"); + + List travelDealList = travelDealRepository.findAll(); + if (!travelDealList.isEmpty()) { + int randomDeal = new Random().nextInt(travelDealList.size()); + return travelDealList.get(randomDeal).toString(); + } else { + return "NO DEALS"; + } + } + + @RequestMapping(method = GET, path = "/") + @ResponseBody + public String get() throws UnknownHostException { + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Host: ").append(InetAddress.getLocalHost().getHostName()).append("
"); + stringBuilder.append("IP: ").append(InetAddress.getLocalHost().getHostAddress()).append("
"); + stringBuilder.append("Type: ").append("Travel Agency").append("
"); + return stringBuilder.toString(); + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java new file mode 100644 index 0000000000..550b2ca33c --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java @@ -0,0 +1,100 @@ +package com.baeldung.spring.cloud.kubernetes.travelagency.model; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +import java.math.BigInteger; +import java.util.Date; + +@Document(collection = "travel_deal") +public class TravelDeal { + + @Id + private BigInteger id; + + private String destination; + + private String description; + + @Field("deal_price") + private double dealPrice; + + @Field("old_price") + private double oldPrice; + + @Field("departure_date") + private Date departureDate; + + @Field("arrival_date") + private Date arrivalDate; + + public BigInteger getId() { + return id; + } + + public void setId(BigInteger id) { + this.id = id; + } + + public String getDestination() { + return destination; + } + + public void setDestination(String destination) { + this.destination = destination; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public double getDealPrice() { + return dealPrice; + } + + public void setDealPrice(double dealPrice) { + this.dealPrice = dealPrice; + } + + public double getOldPrice() { + return oldPrice; + } + + public void setOldPrice(double oldPrice) { + this.oldPrice = oldPrice; + } + + public Date getDepartureDate() { + return departureDate; + } + + public void setDepartureDate(Date departureDate) { + this.departureDate = departureDate; + } + + public Date getArrivalDate() { + return arrivalDate; + } + + public void setArrivalDate(Date arrivalDate) { + this.arrivalDate = arrivalDate; + } + + @Override + public String toString() { + return "TravelDeal{" + + "id=" + id + + ", destination='" + destination + '\'' + + ", description='" + description + '\'' + + ", dealPrice=" + dealPrice + + ", oldPrice=" + oldPrice + + ", departureDate=" + departureDate + + ", arrivalDate=" + arrivalDate + + '}'; + } +} diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java new file mode 100644 index 0000000000..f7dc5a843e --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.cloud.kubernetes.travelagency.repository; + +import java.util.List; + +import com.baeldung.spring.cloud.kubernetes.travelagency.model.TravelDeal; +import org.springframework.data.mongodb.repository.MongoRepository; + +public interface TravelDealRepository extends MongoRepository { + + public List findByDestination(String destination); + + +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/application.properties b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/application.properties new file mode 100644 index 0000000000..ffe78f0917 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/application.properties @@ -0,0 +1,14 @@ +spring.application.name=travel-agency-service +server.port=8080 +spring.cloud.kubernetes.reload.enabled=true +spring.cloud.kubernetes.secrets.name=db-secret +spring.data.mongodb.host=mongodb-service +spring.data.mongodb.port=27017 +spring.data.mongodb.database=admin +spring.data.mongodb.username=${MONGO_USERNAME} +spring.data.mongodb.password=${MONGO_PASSWORD} +management.endpoint.health.enabled=true +management.endpoint.info.enabled=true +management.endpoint.restart.enabled=true +com.baeldung.spring.cloud.kubernetes.services=debug + diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback-spring.xml b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..49aeda8f9f --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback-spring.xml @@ -0,0 +1,17 @@ + + + + + + logstash:5000 + + + + + + + + + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback.xml b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback.xml new file mode 100644 index 0000000000..37492be5bf --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + + + + diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-config.yaml b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-config.yaml new file mode 100644 index 0000000000..93a67e3777 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-config.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: travel-agency-service +data: + application.properties: |- + bean.message=Testing reload ! Message from backend is: %s
Services : %s + diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-deployment.yaml b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-deployment.yaml new file mode 100644 index 0000000000..a41f13bf61 --- /dev/null +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-deployment.yaml @@ -0,0 +1,44 @@ +kind: Service +apiVersion: v1 +metadata: + name: travel-agency-service +spec: + selector: + app: travel-agency-service + ports: + - protocol: TCP + port: 8080 + nodePort: 30081 + type: NodePort +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: travel-agency-service +spec: + selector: + matchLabels: + app: travel-agency-service + replicas: 2 + template: + metadata: + labels: + app: travel-agency-service + spec: + containers: + - name: travel-agency-service + image: travel-agency-service:latest + imagePullPolicy: Never + ports: + - containerPort: 8080 + env: + - name: MONGO_USERNAME + valueFrom: + secretKeyRef: + name: db-secret + key: username + - name: MONGO_PASSWORD + valueFrom: + secretKeyRef: + name: db-secret + key: password \ No newline at end of file From 12b3bc1383ae32df25b43587045b0cfd1e1994a5 Mon Sep 17 00:00:00 2001 From: cscib Date: Sun, 10 Mar 2019 22:31:20 +0100 Subject: [PATCH 292/496] Delete Dockerfile --- .../client-service/Dockerfile | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/Dockerfile diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes-project/client-service/Dockerfile deleted file mode 100644 index 93e75216db..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/client-service/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -# requires Docker version 17.05.0-ce-rc1, build 2878a85 -FROM maven:3.5-jdk-8 as BUILDAGENCY - -COPY src /usr/src/myapp/src -COPY pom.xml /usr/src/myapp -RUN mvn -f /usr/src/myapp/pom.xml clean package -DskipTests - -FROM openjdk:alpine - -COPY --from=BUILDAGENCY /usr/src/myapp/target/*.jar /maven/ - -CMD java $JAVA_OPTS -jar maven/*.jar \ No newline at end of file From ea3fe7aab95eb068e3255cc6da501c25e37c85b5 Mon Sep 17 00:00:00 2001 From: caroline Date: Sun, 10 Mar 2019 22:34:17 +0100 Subject: [PATCH 293/496] Removing the code of an old version of the code with deleted maven module spring-cloud-kubernetes-project --- .../client-service/pom.xml | 71 -------------- .../services/client/ClientApplication.java | 96 ------------------- .../services/client/config/ClientConfig.java | 19 ---- .../client/controller/ClientController.java | 43 --------- .../service/TravelAgencyClientService.java | 45 --------- .../src/main/resources/bootstrap.yml | 6 -- .../gateway-service/Dockerfile | 12 --- .../gateway-service/pom.xml | 76 --------------- .../services/gateway/GatewayApplication.java | 44 --------- .../src/main/resources/bootstrap.yml | 6 -- .../spring-cloud-kubernetes-project/pom.xml | 27 ------ .../travel-agency-service/Dockerfile | 12 --- .../travel-agency-service/pom.xml | 59 ------------ .../travelagency/TravelAgencyApplication.java | 24 ----- .../controller/TravelAgencyController.java | 36 ------- .../src/main/resources/bootstrap.yml | 6 -- 16 files changed, 582 deletions(-) delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/pom.xml delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/ClientApplication.java delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/config/ClientConfig.java delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/controller/ClientController.java delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/service/TravelAgencyClientService.java delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/resources/bootstrap.yml delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/gateway-service/Dockerfile delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/gateway-service/pom.xml delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/gateway/GatewayApplication.java delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/resources/bootstrap.yml delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/pom.xml delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/Dockerfile delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/pom.xml delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/TravelAgencyApplication.java delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/controller/TravelAgencyController.java delete mode 100644 spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/resources/bootstrap.yml diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/pom.xml b/spring-cloud/spring-cloud-kubernetes-project/client-service/pom.xml deleted file mode 100644 index 6bba5512cd..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/client-service/pom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE - - client-service - com.baeldung.spring.cloud - 1.0-SNAPSHOT - - - 1.8 - 2.0.1.RELEASE - Finchley.SR2 - 0.3.0.RELEASE - - - - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud-dependencies.version} - pom - import - - - org.springframework.cloud - spring-cloud-kubernetes-dependencies - ${spring.cloud.k8s.version} - pom - import - - - - - - - org.springframework.cloud - spring-cloud-kubernetes-discovery - - - org.springframework.cloud - spring-cloud-starter-kubernetes-config - - - org.springframework.cloud - spring-cloud-starter-netflix-hystrix - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-actuator - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/ClientApplication.java b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/ClientApplication.java deleted file mode 100644 index 9044de9574..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/ClientApplication.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.baeldung.spring.cloud.kubernetes.services.department; - -import com.baeldung.spring.cloud.kubernetes.services.client.config.ClientConfig; -import com.baeldung.spring.cloud.kubernetes.services.client.service.TravelAgencyClientService; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.context.annotation.Bean; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.web.client.RestTemplate; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.List; -import java.util.Map; - -@SpringBootApplication -@EnableDiscoveryClient -@EnableCircuitBreaker -public class ClientApplication implements CommandLineRunner { - - private static final Log log = LogFactory.getLog(ClientApplication.class); - private static final String FIND_TRAVEL_DEALS_TASK = "Find new travel deals"; - - @Autowired - private DiscoveryClient discoveryClient; - - @Autowired - private TravelAgencyClientService travelAgencyClient; - - @Autowired - private ClientConfig clientConfig; - - private String task = FIND_TRAVEL_DEALS_TASK; - - @Bean - private RestTemplate restTemplate() { - return new RestTemplate(); - } - - @Value("${spring.application.name}") - private String appName; - - public static void main(String[] args) { - SpringApplication.run(ClientApplication.class, args); - } - - @Override - public void run(String... args) { - log.info("Client (" + appName + ":" + clientConfig.getType() + ")Started! "); - } - - /* - * Every 10 seconds look for new deals - */ - @Scheduled(fixedRate = 10000) - public void doSomeWork() throws UnknownHostException { - if (task.equals(FIND_TRAVEL_DEALS_TASK)) { - task = findNewDeals(); - if (task.equals(FIND_TRAVEL_DEALS_TASK)) { - log.info("NO DEAL FOUND, I will keep looking for one "); - } - } - log.info(">>> Working on " + task); - } - - - - - private String findNewDeals() throws UnknownHostException { - List services = this.discoveryClient.getServices(); - - for (String service : services) { - List instances = this.discoveryClient.getInstances(service); - for (ServiceInstance se : instances) { - Map metadata = se.getMetadata(); - String type = metadata.get("type"); - if ("deal".equals(type)) { - - String from = appName + "@" + InetAddress.getLocalHost().getHostName(); - String url = "http://" + se.getServiceId(); - return travelAgencyClient.requestDeals(url, from); - } - } - } - return FIND_TRAVEL_DEALS_TASK; - } -} diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/config/ClientConfig.java b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/config/ClientConfig.java deleted file mode 100644 index a4f43e2ddc..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/config/ClientConfig.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.spring.cloud.kubernetes.services.client.config; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConfigurationProperties(prefix = "client") -public class ClientConfig { - - private String type = "generic-client"; - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } -} diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/controller/ClientController.java b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/controller/ClientController.java deleted file mode 100644 index dad736953e..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/controller/ClientController.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.baeldung.spring.cloud.kubernetes.services.client.controller; - -import java.io.UnsupportedEncodingException; -import java.net.InetAddress; -import java.net.UnknownHostException; - -import com.baeldung.spring.cloud.kubernetes.services.client.config.ClientConfig; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import static org.springframework.web.bind.annotation.RequestMethod.GET; - -@RestController -@RefreshScope -public class ClientController { - - private static final Log log = LogFactory.getLog(ClientController.class); - - private enum ClientTravelType { - BUSINESS, - STUDENT, - COUPLE, - FRIENDS, - SINGLE, - FAMILY; - } - - @Autowired - private ClientConfig clientConfig; - - @RequestMapping(method = GET) - public String get() throws UnknownHostException, UnsupportedEncodingException { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Host: ").append(InetAddress.getLocalHost().getHostName()).append("
"); - stringBuilder.append("Client Type: ").append(clientConfig.getType()).append("
"); - stringBuilder.append("IP: ").append(InetAddress.getLocalHost().getHostAddress()).append("
"); - return stringBuilder.toString(); - } -} diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/service/TravelAgencyClientService.java b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/service/TravelAgencyClientService.java deleted file mode 100644 index ba86808cd5..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/client/service/TravelAgencyClientService.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.baeldung.spring.cloud.kubernetes.services.client.service; - -import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; -import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -@Service -public class TravelAgencyClientService { - - private final RestTemplate restTemplate; - - private static final Log log = LogFactory.getLog(TravelAgencyClientService.class); - - public static final String FIND_NEW_TRAVEL_DEALS = "find new travel deals"; - - public TravelAgencyClientService(RestTemplate restTemplate) { - this.restTemplate = restTemplate; - } - - @HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = { - @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000") - }) - public String requestDeals(String to, - String from) { - - String url = String.format("%s/deals/%s", - to, - from); - - log.info("--- Requesting travel deals to travel agency " + url); - - return restTemplate.getForObject(url, String.class); - } - - private String getFallbackName(String to, - String from) { - log.error("--- This travel agency (" + to + ") not available now, please come back later (Fallback) client:" + from); - return FIND_NEW_TRAVEL_DEALS; - } -} diff --git a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/resources/bootstrap.yml deleted file mode 100644 index 736a17b041..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/client-service/src/main/resources/bootstrap.yml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - application: - name: client-service - cloud: - config: - uri: http://localhost:8088 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/Dockerfile deleted file mode 100644 index 93e75216db..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -# requires Docker version 17.05.0-ce-rc1, build 2878a85 -FROM maven:3.5-jdk-8 as BUILDAGENCY - -COPY src /usr/src/myapp/src -COPY pom.xml /usr/src/myapp -RUN mvn -f /usr/src/myapp/pom.xml clean package -DskipTests - -FROM openjdk:alpine - -COPY --from=BUILDAGENCY /usr/src/myapp/target/*.jar /maven/ - -CMD java $JAVA_OPTS -jar maven/*.jar \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/pom.xml b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/pom.xml deleted file mode 100644 index 84eb353fb9..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/pom.xml +++ /dev/null @@ -1,76 +0,0 @@ - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE - - gateway-service - com.baeldung.spring.cloud - 1.0-SNAPSHOT - - - 1.8 - 2.0.1.RELEASE - Finchley.SR2 - 0.3.0.RELEASE - - - - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud-dependencies.version} - pom - import - - - org.springframework.cloud - spring-cloud-kubernetes-dependencies - ${spring.cloud.k8s.version} - pom - import - - - - - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-autoconfigure - - - org.springframework.cloud - spring-cloud-starter-netflix-hystrix - - - org.springframework.cloud - spring-cloud-starter-gateway - - - org.springframework.cloud - spring-cloud-kubernetes-discovery - - - org.springframework.cloud - spring-cloud-kubernetes-ribbon - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/gateway/GatewayApplication.java b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/gateway/GatewayApplication.java deleted file mode 100644 index 7f11906aba..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/gateway/GatewayApplication.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.spring.cloud.kubernetes.services.gateway; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.DiscoveryClient; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.cloud.client.loadbalancer.LoadBalanced; -import org.springframework.cloud.gateway.discovery.DiscoveryClientRouteDefinitionLocator; -import org.springframework.cloud.gateway.discovery.DiscoveryLocatorProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.web.client.RestTemplate; - -@EnableScheduling -@EnableDiscoveryClient -@SpringBootApplication -public class GatewayApplication { - - private static final Log log = LogFactory.getLog(GatewayApplication.class); - - @Autowired - private DiscoveryClient discoveryClient; - - @Bean - public DiscoveryClientRouteDefinitionLocator discoveryClientRouteLocator(DiscoveryClient discoveryClient, - DiscoveryLocatorProperties properties) { - return new DiscoveryClientRouteDefinitionLocator(discoveryClient, - properties); - } - - public static void main(String[] args) { - SpringApplication.run(GatewayApplication.class, - args); - } - - @LoadBalanced - @Bean - RestTemplate restTemplate() { - return new RestTemplate(); - } -} diff --git a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/resources/bootstrap.yml deleted file mode 100644 index 5fd607d335..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/gateway-service/src/main/resources/bootstrap.yml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - application: - name: gateway-service - cloud: - config: - uri: http://localhost:8088 \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/pom.xml b/spring-cloud/spring-cloud-kubernetes-project/pom.xml deleted file mode 100644 index dc4e3bfe70..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - 4.0.0 - com.baeldung.spring.cloud - spring-cloud-kubernetes-project - 1.0.0-SNAPSHOT - spring-cloud-kubernetes-project - Spring Cloud Kubernetes - pom - - - travel-agency-service - client-service - gateway-service - - - - com.baeldung.spring.cloud - spring-cloud - 1.0.0-SNAPSHOT - .. - - - - - diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/Dockerfile deleted file mode 100644 index 93e75216db..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -# requires Docker version 17.05.0-ce-rc1, build 2878a85 -FROM maven:3.5-jdk-8 as BUILDAGENCY - -COPY src /usr/src/myapp/src -COPY pom.xml /usr/src/myapp -RUN mvn -f /usr/src/myapp/pom.xml clean package -DskipTests - -FROM openjdk:alpine - -COPY --from=BUILDAGENCY /usr/src/myapp/target/*.jar /maven/ - -CMD java $JAVA_OPTS -jar maven/*.jar \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/pom.xml b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/pom.xml deleted file mode 100644 index 69cd22ae52..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.0.6.RELEASE - - travel-agency-service - com.baeldung.spring.cloud - 1.0-SNAPSHOT - - - 1.8 - 2.0.1.RELEASE - Finchley.SR2 - - - - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud-dependencies.version} - pom - import - - - - - - - org.springframework.cloud - spring-cloud-starter-netflix-eureka-client - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-actuator - - - org.springframework.boot - spring-boot-actuator-autoconfigure - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/TravelAgencyApplication.java b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/TravelAgencyApplication.java deleted file mode 100644 index c96b547e18..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/TravelAgencyApplication.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.spring.cloud.kubernetes.services.department; - -import com.baeldung.spring.cloud.kubernetes.services.travelagency.controller.TravelAgencyController; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class TravelAgencyApplication implements CommandLineRunner { - - private static final Log log = LogFactory.getLog(TravelAgencyController.class); - - public static void main(String[] args) { - SpringApplication.run(TravelAgencyApplication.class, args); - } - - @Override - public void run(String... args) throws Exception { - log.info("Travel Agency Started! "); - } - -} diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/controller/TravelAgencyController.java b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/controller/TravelAgencyController.java deleted file mode 100644 index ec84debe83..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/services/travelagency/controller/TravelAgencyController.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.spring.cloud.kubernetes.services.travelagency.controller; - -import org.springframework.web.bind.annotation.*; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Random; -import static org.springframework.web.bind.annotation.RequestMethod.GET; -import static org.springframework.web.bind.annotation.RequestMethod.POST; - -@RestController -public class TravelAgencyController { - - private String[] deals = {"London - Paris : 25 Euro", "London - Frankfurt : 25 Euro"}; - private static final Log log = LogFactory.getLog(TravelAgencyController.class); - - - @RequestMapping(method = POST, path = "/deals/{client}") - public String deals(@PathVariable("client") String client) { - log.info("Client: " + client + " is requesting new deals!"); - int randomDeal = new Random().nextInt(deals.length); - return deals[randomDeal]; - } - - @RequestMapping(method = GET, path = "/") - @ResponseBody - public String get() throws UnknownHostException { - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Host: ").append(InetAddress.getLocalHost().getHostName()).append("
"); - stringBuilder.append("IP: ").append(InetAddress.getLocalHost().getHostAddress()).append("
"); - stringBuilder.append("Type: ").append("Travel Agency").append("
"); - return stringBuilder.toString(); - } -} diff --git a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/resources/bootstrap.yml b/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/resources/bootstrap.yml deleted file mode 100644 index d9fd0c0e76..0000000000 --- a/spring-cloud/spring-cloud-kubernetes-project/travel-agency-service/src/main/resources/bootstrap.yml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - application: - name: travelagency-service - cloud: - config: - uri: http://localhost:8088 \ No newline at end of file From 1131705393d1cc04cb1c8166b7fdbd19f29128f7 Mon Sep 17 00:00:00 2001 From: Dhananjay Singh Date: Mon, 11 Mar 2019 00:30:33 +0100 Subject: [PATCH 294/496] REST-assured web --- testing-modules/rest-assured/pom.xml | 37 +++-- .../com/baeldung/restassured/Application.java | 13 ++ .../restassured/controller/AppController.java | 100 ++++++++++++ .../com/baeldung/restassured/model/Movie.java | 58 +++++++ .../restassured/service/AppService.java | 45 ++++++ .../rest-assured/src/main/resources/1 | 1 + .../rest-assured/src/main/resources/2 | 1 + .../AppControllerIntegrationTest.java | 142 ++++++++++++++++++ .../rest-assured/src/test/resources/test.txt | 1 + 9 files changed, 379 insertions(+), 19 deletions(-) create mode 100644 testing-modules/rest-assured/src/main/java/com/baeldung/restassured/Application.java create mode 100644 testing-modules/rest-assured/src/main/java/com/baeldung/restassured/controller/AppController.java create mode 100644 testing-modules/rest-assured/src/main/java/com/baeldung/restassured/model/Movie.java create mode 100644 testing-modules/rest-assured/src/main/java/com/baeldung/restassured/service/AppService.java create mode 100644 testing-modules/rest-assured/src/main/resources/1 create mode 100644 testing-modules/rest-assured/src/main/resources/2 create mode 100644 testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java create mode 100644 testing-modules/rest-assured/src/test/resources/test.txt diff --git a/testing-modules/rest-assured/pom.xml b/testing-modules/rest-assured/pom.xml index 687a9a2fe4..1d6b7fe933 100644 --- a/testing-modules/rest-assured/pom.xml +++ b/testing-modules/rest-assured/pom.xml @@ -8,16 +8,30 @@ com.baeldung - parent-java + parent-boot-2 0.0.1-SNAPSHOT - ../../parent-java + ../../parent-boot-2 + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + com.google.guava + guava + 18.0 + javax.servlet javax.servlet-api - ${javax.servlet-api.version} javax.servlet @@ -27,49 +41,40 @@ org.eclipse.jetty jetty-security - ${jetty.version} org.eclipse.jetty jetty-servlet - ${jetty.version} org.eclipse.jetty jetty-servlets - ${jetty.version} org.eclipse.jetty jetty-io - ${jetty.version} org.eclipse.jetty jetty-http - ${jetty.version} org.eclipse.jetty jetty-server - ${jetty.version} org.eclipse.jetty jetty-util - ${jetty.version} org.apache.httpcomponents httpcore - ${httpcore.version} org.apache.commons commons-lang3 - ${commons-lang3.version} @@ -92,19 +97,16 @@ joda-time - joda-time - ${joda-time.version} + joda-time com.fasterxml.jackson.core jackson-annotations - ${jackson.version} com.fasterxml.jackson.core jackson-databind - ${jackson.version} @@ -128,7 +130,6 @@ org.apache.httpcomponents httpclient - ${httpclient.version} @@ -145,13 +146,11 @@ io.rest-assured rest-assured - ${rest-assured.version} test io.rest-assured json-schema-validator - ${rest-assured-json-schema-validator.version} com.github.fge diff --git a/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/Application.java b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/Application.java new file mode 100644 index 0000000000..8b53a9c63d --- /dev/null +++ b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/Application.java @@ -0,0 +1,13 @@ +package com.baeldung.restassured; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/controller/AppController.java b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/controller/AppController.java new file mode 100644 index 0000000000..d68ebf4b03 --- /dev/null +++ b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/controller/AppController.java @@ -0,0 +1,100 @@ +package com.baeldung.restassured.controller; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.Set; +import java.util.UUID; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.InputStreamResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +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.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.restassured.model.Movie; +import com.baeldung.restassured.service.AppService; + +@RestController +public class AppController { + + @Autowired + AppService appService; + + @GetMapping("/movies") + public ResponseEntity getMovies() { + + Set result = appService.getAll(); + + return ResponseEntity.ok() + .body(result); + } + + @PostMapping("/movie") + @ResponseStatus(HttpStatus.CREATED) + public Movie addMovie(@RequestBody Movie movie) { + + appService.add(movie); + return movie; + } + + @GetMapping("/movie/{id}") + public ResponseEntity getMovie(@PathVariable int id) { + + Movie movie = appService.findMovie(id); + if (movie == null) { + return ResponseEntity.badRequest() + .body("Invalid movie id"); + } + + return ResponseEntity.ok(movie); + } + + @GetMapping("/welcome") + public ResponseEntity welcome(HttpServletResponse response) { + + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_TYPE, "application/json; charset=UTF-8"); + headers.add("sessionId", UUID.randomUUID() + .toString()); + + Cookie cookie = new Cookie("token", "some-token"); + cookie.setDomain("localhost"); + + response.addCookie(cookie); + + return ResponseEntity.noContent() + .headers(headers) + .build(); + } + + @GetMapping("/download/{id}") + public ResponseEntity getFile(@PathVariable int id) throws FileNotFoundException { + + File file = appService.getFile(id); + + if (file == null) { + return ResponseEntity.notFound() + .build(); + } + + InputStreamResource resource = new InputStreamResource(new FileInputStream(file)); + + return ResponseEntity.ok() + .contentLength(file.length()) + .contentType(MediaType.parseMediaType("application/octet-stream")) + .body(resource); + } + +} diff --git a/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/model/Movie.java b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/model/Movie.java new file mode 100644 index 0000000000..00a446fc65 --- /dev/null +++ b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/model/Movie.java @@ -0,0 +1,58 @@ +package com.baeldung.restassured.model; + +public class Movie { + + private Integer id; + + private String name; + + private String synopsis; + + public Movie() { + } + + public Movie(Integer id, String name, String synopsis) { + super(); + this.id = id; + this.name = name; + this.synopsis = synopsis; + } + + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + + public String getSynopsis() { + return synopsis; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Movie other = (Movie) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + +} diff --git a/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/service/AppService.java b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/service/AppService.java new file mode 100644 index 0000000000..15685f2924 --- /dev/null +++ b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/service/AppService.java @@ -0,0 +1,45 @@ +package com.baeldung.restassured.service; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Service; + +import com.baeldung.restassured.model.Movie; + +@Service +public class AppService { + + private Set movieSet = new HashSet<>(); + + public Set getAll() { + return movieSet; + } + + public void add(Movie movie) { + movieSet.add(movie); + } + + public Movie findMovie(int id) { + return movieSet.stream() + .filter(movie -> movie.getId() + .equals(id)) + .findFirst() + .orElse(null); + } + + public File getFile(int id) { + File file = null; + try { + file = new ClassPathResource(String.valueOf(id)).getFile(); + } catch (IOException e) { + e.printStackTrace(); + } + + return file; + } + +} diff --git a/testing-modules/rest-assured/src/main/resources/1 b/testing-modules/rest-assured/src/main/resources/1 new file mode 100644 index 0000000000..49351eb5b7 --- /dev/null +++ b/testing-modules/rest-assured/src/main/resources/1 @@ -0,0 +1 @@ +File 1 \ No newline at end of file diff --git a/testing-modules/rest-assured/src/main/resources/2 b/testing-modules/rest-assured/src/main/resources/2 new file mode 100644 index 0000000000..9fbb45ed08 --- /dev/null +++ b/testing-modules/rest-assured/src/main/resources/2 @@ -0,0 +1 @@ +File 2 \ No newline at end of file diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java new file mode 100644 index 0000000000..9ad940683f --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java @@ -0,0 +1,142 @@ +package com.baeldung.restassured.controller; + +import static io.restassured.RestAssured.get; +import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.annotation.PostConstruct; + +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.core.io.ClassPathResource; +import org.springframework.http.HttpStatus; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.restassured.model.Movie; +import com.baeldung.restassured.service.AppService; + +import io.restassured.response.Response; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class AppControllerIntegrationTest { + + @LocalServerPort + private int port; + + private String uri; + + @PostConstruct + public void init() { + uri = "http://localhost:" + port; + } + + @MockBean + AppService appService; + + @Test + public void givenMovieId_whenMakingGetRequestToMovieEndpoint_thenReturnMovie() { + + Movie testMovie = new Movie(1, "movie1", "summary1"); + when(appService.findMovie(1)).thenReturn(testMovie); + + get(uri + "/movie/" + testMovie.getId()).then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .body("id", equalTo(testMovie.getId())) + .body("name", equalTo(testMovie.getName())) + .body("synopsis", equalTo(testMovie.getSynopsis())); + + Movie result = get(uri + "/movie/" + testMovie.getId()).then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .extract() + .as(Movie.class); + assertThat(result).isEqualTo(testMovie); + } + + @Test + public void whenCallingMoviesEndpoint_thenReturnAllMovies() { + + Set movieSet = new HashSet<>(); + movieSet.add(new Movie(1, "movie1", "summary1")); + movieSet.add(new Movie(2, "movie2", "summary2")); + when(appService.getAll()).thenReturn(movieSet); + + get(uri + "/movies").then() + .statusCode(HttpStatus.OK.value()) + .assertThat() + .body("size()", is(2)); + + Movie[] movies = get(uri + "/movies").then() + .statusCode(200) + .extract() + .as(Movie[].class); + assertThat(movies.length).isEqualTo(2); + } + + @Test + public void givenMovie_whenMakingPostRequestToMovieEndpoint_thenCorrect() { + + Map request = new HashMap<>(); + request.put("id", "11"); + request.put("name", "movie1"); + request.put("synopsis", "summary1"); + + int movieId = given().contentType("application/json") + .body(request) + .when() + .post(uri + "/movie") + .then() + .assertThat() + .statusCode(HttpStatus.CREATED.value()) + .extract() + .path("id"); + assertThat(movieId).isEqualTo(11); + + } + + @Test + public void whenCallingWelcomeEndpoint_thenCorrect() { + + get(uri + "/welcome").then() + .assertThat() + .header("sessionId", notNullValue()) + .cookie("token", notNullValue()); + + Response response = get(uri + "/welcome"); + + String headerName = response.getHeader("sessionId"); + String cookieValue = response.getCookie("token"); + assertThat(headerName).isNotBlank(); + assertThat(cookieValue).isNotBlank(); + } + + @Test + public void givenId_whenCallingDowloadEndpoint_thenCorrect() throws IOException { + + File file = new ClassPathResource("test.txt").getFile(); + long fileSize = file.length(); + when(appService.getFile(1)).thenReturn(file); + + byte[] result = get(uri + "/download/1").asByteArray(); + + assertThat(result.length).isEqualTo(fileSize); + } + +} diff --git a/testing-modules/rest-assured/src/test/resources/test.txt b/testing-modules/rest-assured/src/test/resources/test.txt new file mode 100644 index 0000000000..84362ca046 --- /dev/null +++ b/testing-modules/rest-assured/src/test/resources/test.txt @@ -0,0 +1 @@ +Test file \ No newline at end of file From 3d5fde2a30e6b7c8c0a0efa210ee1101bb932684 Mon Sep 17 00:00:00 2001 From: Dhananjay Singh Date: Mon, 11 Mar 2019 00:42:05 +0100 Subject: [PATCH 295/496] Mover version down --- testing-modules/rest-assured/pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testing-modules/rest-assured/pom.xml b/testing-modules/rest-assured/pom.xml index 1d6b7fe933..8128cd0b3f 100644 --- a/testing-modules/rest-assured/pom.xml +++ b/testing-modules/rest-assured/pom.xml @@ -27,7 +27,7 @@ com.google.guava guava - 18.0 + ${guava.version} javax.servlet @@ -170,6 +170,7 @@ + 18.0 2.9.7 1.8 19.0 From da2f95bfa39dc24a8a12750e28497618c67eb41d Mon Sep 17 00:00:00 2001 From: Rodrigo Graciano Date: Sun, 10 Mar 2019 20:34:19 -0400 Subject: [PATCH 296/496] BAEL-2760 --- .../kotlin/com/baeldung/range/CustomColor.kt | 56 +++++++++++++++++++ .../com/baeldung/range/CustomColorTest.kt | 41 ++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 core-kotlin-2/src/main/kotlin/com/baeldung/range/CustomColor.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/CustomColorTest.kt diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/range/CustomColor.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/CustomColor.kt new file mode 100644 index 0000000000..b4fed13b18 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/range/CustomColor.kt @@ -0,0 +1,56 @@ +package com.baeldung.range + +import java.lang.IllegalStateException + +class CustomColor(val rgb: Int): Comparable { + + override fun compareTo(other: CustomColor): Int { + return this.rgb.compareTo(other.rgb) + } + + operator fun rangeTo(that: CustomColor) = ColorRange(this,that) + + operator fun inc(): CustomColor { + return CustomColor(rgb + 1) + } + + init { + if(rgb < 0x000000 || rgb > 0xFFFFFF){ + throw IllegalStateException("RGB must be between 0 and 16777215") + } + } + + override fun toString(): String { + return "CustomColor(rgb=$rgb)" + } +} +class ColorRange(override val start: CustomColor, + override val endInclusive: CustomColor) : ClosedRange, Iterable{ + + override fun iterator(): Iterator { + return ColorIterator(start, endInclusive) + } +} + +class ColorIterator(val start: CustomColor, val endInclusive: CustomColor) : Iterator { + + var initValue = start + + override fun hasNext(): Boolean { + return initValue <= endInclusive + } + + override fun next(): CustomColor { + return initValue++ + } +} + +fun main(args: Array) { + val a = CustomColor(0xABCDEF) + val b = CustomColor(-1) + val c = CustomColor(0xABCDFF) + + for(color in a..c){ + println(color) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/CustomColorTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/CustomColorTest.kt new file mode 100644 index 0000000000..8c8795ac42 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/CustomColorTest.kt @@ -0,0 +1,41 @@ +package com.baeldung.range + +import org.junit.Test +import java.lang.IllegalStateException +import kotlin.test.assertFailsWith +import kotlin.test.assertTrue + +class CustomColorTest { + + @Test + fun testInvalidConstructor(){ + assertFailsWith(IllegalStateException::class){ + CustomColor(-1) + } + } + + @Test + fun assertHas10Colors(){ + assertTrue { + val a = CustomColor(1) + val b = CustomColor(10) + val range = a..b + for(cc in range){ + println(cc) + } + range.toList().size == 10 + } + } + + @Test + fun assertContains0xCCCCCC(){ + assertTrue { + val a = CustomColor(0xBBBBBB) + val b = CustomColor(0xDDDDDD) + val range = a..b + range.contains(CustomColor(0xCCCCCC)) + } + } + +} + From 6ab2e7a71a84cbe8808d501b51f98cee64abb109 Mon Sep 17 00:00:00 2001 From: Rodrigo Graciano Date: Sun, 10 Mar 2019 20:34:19 -0400 Subject: [PATCH 297/496] BAEL-2760 --- .../kotlin/com/baeldung/range/CustomColor.kt | 56 +++++++++++++++++++ .../com/baeldung/range/CustomColorTest.kt | 41 ++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 core-kotlin-2/src/main/kotlin/com/baeldung/range/CustomColor.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/range/CustomColorTest.kt diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/range/CustomColor.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/range/CustomColor.kt new file mode 100644 index 0000000000..b4fed13b18 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/range/CustomColor.kt @@ -0,0 +1,56 @@ +package com.baeldung.range + +import java.lang.IllegalStateException + +class CustomColor(val rgb: Int): Comparable { + + override fun compareTo(other: CustomColor): Int { + return this.rgb.compareTo(other.rgb) + } + + operator fun rangeTo(that: CustomColor) = ColorRange(this,that) + + operator fun inc(): CustomColor { + return CustomColor(rgb + 1) + } + + init { + if(rgb < 0x000000 || rgb > 0xFFFFFF){ + throw IllegalStateException("RGB must be between 0 and 16777215") + } + } + + override fun toString(): String { + return "CustomColor(rgb=$rgb)" + } +} +class ColorRange(override val start: CustomColor, + override val endInclusive: CustomColor) : ClosedRange, Iterable{ + + override fun iterator(): Iterator { + return ColorIterator(start, endInclusive) + } +} + +class ColorIterator(val start: CustomColor, val endInclusive: CustomColor) : Iterator { + + var initValue = start + + override fun hasNext(): Boolean { + return initValue <= endInclusive + } + + override fun next(): CustomColor { + return initValue++ + } +} + +fun main(args: Array) { + val a = CustomColor(0xABCDEF) + val b = CustomColor(-1) + val c = CustomColor(0xABCDFF) + + for(color in a..c){ + println(color) + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/range/CustomColorTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/range/CustomColorTest.kt new file mode 100644 index 0000000000..8c8795ac42 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/range/CustomColorTest.kt @@ -0,0 +1,41 @@ +package com.baeldung.range + +import org.junit.Test +import java.lang.IllegalStateException +import kotlin.test.assertFailsWith +import kotlin.test.assertTrue + +class CustomColorTest { + + @Test + fun testInvalidConstructor(){ + assertFailsWith(IllegalStateException::class){ + CustomColor(-1) + } + } + + @Test + fun assertHas10Colors(){ + assertTrue { + val a = CustomColor(1) + val b = CustomColor(10) + val range = a..b + for(cc in range){ + println(cc) + } + range.toList().size == 10 + } + } + + @Test + fun assertContains0xCCCCCC(){ + assertTrue { + val a = CustomColor(0xBBBBBB) + val b = CustomColor(0xDDDDDD) + val range = a..b + range.contains(CustomColor(0xCCCCCC)) + } + } + +} + From c59211f756f46e818fc766b9f2e01e99e9267c88 Mon Sep 17 00:00:00 2001 From: kwoyke Date: Mon, 11 Mar 2019 03:18:23 +0100 Subject: [PATCH 298/496] BAEL-2776 Chaining Optionals in Java 8 (#6502) * BAEL-2776 Chaining Optionals in Java 8 * BAEL-2776 Improvements after the first review --- .../optional/OptionalChainingUnitTest.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java diff --git a/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java new file mode 100644 index 0000000000..70ec324cb3 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/optional/OptionalChainingUnitTest.java @@ -0,0 +1,110 @@ +package com.baeldung.java8.optional; + +import org.junit.Before; +import org.junit.Test; + +import java.util.Optional; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import static org.junit.Assert.*; + +public class OptionalChainingUnitTest { + + private boolean getEmptyEvaluated; + private boolean getHelloEvaluated; + private boolean getByeEvaluated; + + @Before + public void setUp() { + getEmptyEvaluated = false; + getHelloEvaluated = false; + getByeEvaluated = false; + } + + @Test + public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturned() { + Optional found = Stream.of(getEmpty(), getHello(), getBye()) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); + + assertEquals(getHello(), found); + } + + @Test + public void givenTwoEmptyOptionals_whenChaining_thenEmptyOptionalIsReturned() { + Optional found = Stream.of(getEmpty(), getEmpty()) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); + + assertFalse(found.isPresent()); + } + + @Test + public void givenTwoEmptyOptionals_whenChaining_thenDefaultIsReturned() { + String found = Stream.>>of( + () -> createOptional("empty"), + () -> createOptional("empty") + ) + .map(Supplier::get) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst() + .orElseGet(() -> "default"); + + assertEquals("default", found); + } + + @Test + public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturnedAndRestNotEvaluated() { + Optional found = Stream.>>of(this::getEmpty, this::getHello, this::getBye) + .map(Supplier::get) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); + + assertTrue(this.getEmptyEvaluated); + assertTrue(this.getHelloEvaluated); + assertFalse(this.getByeEvaluated); + assertEquals(getHello(), found); + } + + @Test + public void givenTwoOptionalsReturnedByOneArgMethod_whenChaining_thenFirstNonEmptyIsReturned() { + Optional found = Stream.>>of( + () -> createOptional("empty"), + () -> createOptional("hello") + ) + .map(Supplier::get) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); + + assertEquals(createOptional("hello"), found); + } + + private Optional getEmpty() { + this.getEmptyEvaluated = true; + return Optional.empty(); + } + + private Optional getHello() { + this.getHelloEvaluated = true; + return Optional.of("hello"); + } + + private Optional getBye() { + this.getByeEvaluated = true; + return Optional.of("bye"); + } + + private Optional createOptional(String input) { + if (input == null || input == "" || input == "empty") { + return Optional.empty(); + } + + return Optional.of(input); + } +} \ No newline at end of file From 0530d5c59fe8fcd814d5eaf5fb2ff8ed43f26a9c Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Mon, 11 Mar 2019 11:15:52 +0400 Subject: [PATCH 299/496] primitive maps final --- .../baeldung/primitives/PrimitiveMaps.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java b/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java index eaa7e308bb..89e99acfc7 100644 --- a/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java +++ b/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java @@ -21,37 +21,33 @@ public class PrimitiveMaps { private static void fastutilMap() { Int2BooleanMap int2BooleanMap = new Int2BooleanOpenHashMap(); int2BooleanMap.put(1, true); + int2BooleanMap.put(7, false); + int2BooleanMap.put(4, true); + + boolean value = int2BooleanMap.get(1); Int2BooleanSortedMap int2BooleanSorted = Int2BooleanSortedMaps.EMPTY_MAP; - int2BooleanSorted.putIfAbsent(7, true); - int2BooleanSorted.putIfAbsent(1, true); - int2BooleanSorted.putIfAbsent(4, true); } private static void coltMap() { AbstractIntDoubleMap map = new OpenIntDoubleHashMap(); map.put(1, 4.5); + double value = map.get(1); } private static void eclipseCollectionsMap() { - MutableObjectDoubleMap doubleMap = ObjectDoubleMaps.mutable.empty(); - doubleMap.put("1", 1.0d); - doubleMap.put("2", 2.0d); - - MutableObjectIntMap booleanMap = ObjectIntMaps.mutable.empty(); - booleanMap.put("ok", 1); - MutableIntIntMap mutableIntIntMap = IntIntMaps.mutable.empty(); mutableIntIntMap.addToValue(1, 1); ImmutableIntIntMap immutableIntIntMap = IntIntMaps.immutable.empty(); - MutableObjectIntMap intObject = ObjectIntMaps.mutable.empty(); - intObject.addToValue("price", 2); + MutableObjectDoubleMap dObject = ObjectDoubleMaps.mutable.empty(); + dObject.addToValue("price", 150.5); + dObject.addToValue("quality", 4.4); + dObject.addToValue("stability", 0.8); } private static void troveMap() { - double[] doubles = new double[] {1.2, 4.5, 0.3}; int[] ints = new int[] {1, 4, 0}; @@ -60,7 +56,5 @@ public class PrimitiveMaps { doubleIntMap.adjustValue(1.2, 1); doubleIntMap.adjustValue(4.5, 4); doubleIntMap.adjustValue(0.3, 0); - - System.out.println(doubleIntMap); } } From dcaf1b35a049195e74c4a1c8b7ac719ce7f3f346 Mon Sep 17 00:00:00 2001 From: PranayJain Date: Mon, 11 Mar 2019 13:04:19 +0530 Subject: [PATCH 300/496] BAEL-2719: Skipped conf.properties from packaging --- spring-boot-ops/pom.xml | 9 +++++++++ .../baeldung/properties/ExternalPropertyConfigurer.java | 2 +- .../src/main/resources/external/conf.properties | 4 ++++ .../src/test/resources/external/conf.properties | 3 --- 4 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 spring-boot-ops/src/main/resources/external/conf.properties delete mode 100644 spring-boot-ops/src/test/resources/external/conf.properties diff --git a/spring-boot-ops/pom.xml b/spring-boot-ops/pom.xml index 6c49351820..f36434b682 100644 --- a/spring-boot-ops/pom.xml +++ b/spring-boot-ops/pom.xml @@ -95,6 +95,15 @@ ${project.artifactId} + + + src/main/resources + true + + **/conf.properties + + + org.springframework.boot diff --git a/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyConfigurer.java b/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyConfigurer.java index 67890d717a..0cdbb452d5 100644 --- a/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyConfigurer.java +++ b/spring-boot-ops/src/main/java/com/baeldung/properties/ExternalPropertyConfigurer.java @@ -11,7 +11,7 @@ public class ExternalPropertyConfigurer { @Bean public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer(); - properties.setLocation(new FileSystemResource("src/test/resources/external/conf.properties")); + properties.setLocation(new FileSystemResource("src/main/resources/external/conf.properties")); properties.setIgnoreResourceNotFound(false); return properties; } diff --git a/spring-boot-ops/src/main/resources/external/conf.properties b/spring-boot-ops/src/main/resources/external/conf.properties new file mode 100644 index 0000000000..cfcd23dc76 --- /dev/null +++ b/spring-boot-ops/src/main/resources/external/conf.properties @@ -0,0 +1,4 @@ +url=jdbc:postgresql://localhost:5432/ +username=admin +password=root +spring.main.allow-bean-definition-overriding=true \ No newline at end of file diff --git a/spring-boot-ops/src/test/resources/external/conf.properties b/spring-boot-ops/src/test/resources/external/conf.properties deleted file mode 100644 index da9533fe1f..0000000000 --- a/spring-boot-ops/src/test/resources/external/conf.properties +++ /dev/null @@ -1,3 +0,0 @@ -url=jdbc:postgresql://localhost:5432/ -username=admin -password=root \ No newline at end of file From 24552d68dd0881cabb613669cca71318df9ebb31 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 15:35:25 +0800 Subject: [PATCH 301/496] Update README.MD --- spring-boot/README.MD | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot/README.MD b/spring-boot/README.MD index 28123687fd..223e0959fc 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -36,3 +36,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Display Auto-Configuration Report in Spring Boot](https://www.baeldung.com/spring-boot-auto-configuration-report) - [Injecting Git Information Into Spring](https://www.baeldung.com/spring-git-information) - [Validation in Spring Boot](https://www.baeldung.com/spring-boot-bean-validation) +- [Entity To DTO Conversion for a Spring REST API](https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application) From e82e5b2332192178b3d2f8809f68ab8f854bca6a Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 15:39:07 +0800 Subject: [PATCH 302/496] Update README.md --- core-java-io/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-io/README.md b/core-java-io/README.md index 5e0f7bfbd1..22901b22d5 100644 --- a/core-java-io/README.md +++ b/core-java-io/README.md @@ -40,3 +40,4 @@ - [Create a Directory in Java](https://www.baeldung.com/java-create-directory) - [How to Write to a CSV File in Java](https://www.baeldung.com/java-csv) - [List Files in a Directory in Java](https://www.baeldung.com/java-list-directory-files) +- [Java InputStream to Byte Array and ByteBuffer](https://www.baeldung.com/convert-input-stream-to-array-of-bytes) From c3387be55b9a07d47027fd213b5a6caf5277ebde Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 15:41:51 +0800 Subject: [PATCH 303/496] Update README.md --- core-java-11/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-11/README.md b/core-java-11/README.md index 3c8b94fa28..5e2c07178b 100644 --- a/core-java-11/README.md +++ b/core-java-11/README.md @@ -4,3 +4,4 @@ - [Java 11 Local Variable Syntax for Lambda Parameters](https://www.baeldung.com/java-var-lambda-params) - [Java 11 String API Additions](https://www.baeldung.com/java-11-string-api) - [Java 11 Nest Based Access Control](https://www.baeldung.com/java-nest-based-access-control) +- [Exploring the New HTTP Client in Java 9 and 11](https://www.baeldung.com/java-9-http-client) From 56fb8ec854aab3fdce3377f4efbce469e6bbe54f Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 15:43:11 +0800 Subject: [PATCH 304/496] Update README.md --- core-java/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java/README.md b/core-java/README.md index 67538a3895..ff20f736e0 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -51,3 +51,4 @@ - [Finding Leap Years in Java](https://www.baeldung.com/java-leap-year) - [Java Bitwise Operators](https://www.baeldung.com/java-bitwise-operators) - [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) +- [Sending Emails with Java](https://www.baeldung.com/java-email) From 1c92a79ef98154217b69070c9c2283d41e2b2187 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 16:16:41 +0800 Subject: [PATCH 305/496] Update README.md --- json/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/json/README.md b/json/README.md index c0ca4b00ef..3670b4b9ad 100644 --- a/json/README.md +++ b/json/README.md @@ -13,3 +13,4 @@ - [Get a Value by Key in a JSONArray](https://www.baeldung.com/java-jsonarray-get-value-by-key) - [Iterating Over an Instance of org.json.JSONObject](https://www.baeldung.com/jsonobject-iteration) - [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections) +- [Escape JSON String in Java](https://www.baeldung.com/java-json-escaping) From bd2ce73a89df8499dc76a20f9bf46677981e07af Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 16:18:14 +0800 Subject: [PATCH 306/496] Update README.md --- core-kotlin/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 7d8001d667..95c57336b9 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -54,3 +54,4 @@ - [Nested forEach in Kotlin](https://www.baeldung.com/kotlin-nested-foreach) - [Building DSLs in Kotlin](https://www.baeldung.com/kotlin-dsl) - [Static Methods Behavior in Kotlin](https://www.baeldung.com/kotlin-static-methods) +- [Inline Functions in Kotlin](https://www.baeldung.com/kotlin-inline-functions) From 9672f704bd954acecb35e7c3e44f40578cb948a5 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 16:20:36 +0800 Subject: [PATCH 307/496] Update README.md --- persistence-modules/hibernate-ogm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/hibernate-ogm/README.md b/persistence-modules/hibernate-ogm/README.md index f4a5bb6c3b..508aa77b03 100644 --- a/persistence-modules/hibernate-ogm/README.md +++ b/persistence-modules/hibernate-ogm/README.md @@ -1,4 +1,4 @@ ## Relevant articles: -- [Guide to Hibernate OGM](http://www.baeldung.com/xxxx) +- [Guide to Hibernate OGM](https://www.baeldung.com/hibernate-ogm) From 4f03df3933a431913b9c91b4528d644f07b3fc6c Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 16:22:00 +0800 Subject: [PATCH 308/496] Update README.md --- spring-ehcache/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-ehcache/README.md b/spring-ehcache/README.md index 749441375e..ecf96cd7c7 100644 --- a/spring-ehcache/README.md +++ b/spring-ehcache/README.md @@ -3,5 +3,5 @@ A simple example of using ehcache with spring-boot. ### Relevant Articles: -- [Spring Boot Ehcache Example](http://www.baeldung.com/spring-ehcache) +- [Spring Boot Ehcache Example](https://www.baeldung.com/spring-boot-ehcache) From 82831830c033219d4c8dda0b172c2860f7f92352 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 16:24:08 +0800 Subject: [PATCH 309/496] Update README.md --- core-java-concurrency-advanced/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-java-concurrency-advanced/README.md b/core-java-concurrency-advanced/README.md index bcbec9d687..f48fd30c73 100644 --- a/core-java-concurrency-advanced/README.md +++ b/core-java-concurrency-advanced/README.md @@ -21,4 +21,5 @@ - [Java CyclicBarrier vs CountDownLatch](https://www.baeldung.com/java-cyclicbarrier-countdownlatch) - [Guide to the Fork/Join Framework in Java](http://www.baeldung.com/java-fork-join) - [A Guide to ThreadLocalRandom in Java](http://www.baeldung.com/java-thread-local-random) -- [The Thread.join() Method in Java](http://www.baeldung.com/java-thread-join) \ No newline at end of file +- [The Thread.join() Method in Java](http://www.baeldung.com/java-thread-join) +- [Passing Parameters to Java Threads](https://www.baeldung.com/java-thread-parameters) From bdb05a0073747f1b671f6f42da1d1e23909aff35 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 11 Mar 2019 16:25:52 +0800 Subject: [PATCH 310/496] Update README.md --- jackson/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jackson/README.md b/jackson/README.md index 25194c7255..e9cf6f212c 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -38,3 +38,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Mapping Nested Values with Jackson](http://www.baeldung.com/jackson-nested-values) - [Convert XML to JSON Using Jackson](https://www.baeldung.com/jackson-convert-xml-json) - [Deserialize Immutable Objects with Jackson](https://www.baeldung.com/jackson-deserialize-immutable-objects) +- [Mapping a Dynamic JSON Object with Jackson](https://www.baeldung.com/jackson-mapping-dynamic-object) + From 6cd8c51b4d6182d098c4c0640f0b80759d5b8c86 Mon Sep 17 00:00:00 2001 From: dionisPrifti Date: Mon, 11 Mar 2019 13:43:15 +0100 Subject: [PATCH 311/496] BAEL-2709: Implementing example for Spring Boot Hibernate. (#6478) --- .../application/ExampleApplication.java | 14 +++++++ .../datasources/DataSourceBean.java | 21 ++++++++++ .../application/models/Book.java | 40 +++++++++++++++++++ .../repositories/BookRepository.java | 9 +++++ .../application/services/BookService.java | 19 +++++++++ .../src/main/resources/application.properties | 6 +++ .../tests/BookServiceUnitTest.java | 27 +++++++++++++ .../src/test/resources/application.properties | 2 +- .../src/test/resources/import_books.sql | 3 ++ 9 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/ExampleApplication.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/datasources/DataSourceBean.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/models/Book.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/repositories/BookRepository.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/services/BookService.java create mode 100644 persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothibernate/application/tests/BookServiceUnitTest.java create mode 100644 persistence-modules/spring-boot-persistence/src/test/resources/import_books.sql diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/ExampleApplication.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/ExampleApplication.java new file mode 100644 index 0000000000..4b6a93ab8b --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/ExampleApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.springboothibernate.application; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(ExampleApplication.class, args); + } + +} + diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/datasources/DataSourceBean.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/datasources/DataSourceBean.java new file mode 100644 index 0000000000..54a0c4f077 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/datasources/DataSourceBean.java @@ -0,0 +1,21 @@ +package com.baeldung.springboothibernate.application.datasources; + +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class DataSourceBean { + + @Bean + public DataSource getDataSource() { + DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); + dataSourceBuilder.driverClassName("org.h2.Driver"); + dataSourceBuilder.url("jdbc:h2:mem:test"); + dataSourceBuilder.username("SA"); + dataSourceBuilder.password(""); + return dataSourceBuilder.build(); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/models/Book.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/models/Book.java new file mode 100644 index 0000000000..7562c072c7 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/models/Book.java @@ -0,0 +1,40 @@ +package com.baeldung.springboothibernate.application.models; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Book { + + @Id + @GeneratedValue + private Long id; + private String name; + + public Book() { + super(); + } + + public Book(Long id, String name) { + super(); + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/repositories/BookRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/repositories/BookRepository.java new file mode 100644 index 0000000000..3d5789fb4d --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/repositories/BookRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.springboothibernate.application.repositories; + +import com.baeldung.springboothibernate.application.models.Book; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface BookRepository extends JpaRepository { +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/services/BookService.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/services/BookService.java new file mode 100644 index 0000000000..e495045bab --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/springboothibernate/application/services/BookService.java @@ -0,0 +1,19 @@ +package com.baeldung.springboothibernate.application.services; + +import com.baeldung.springboothibernate.application.models.Book; +import com.baeldung.springboothibernate.application.repositories.BookRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class BookService { + + @Autowired + private BookRepository bookRepository; + + public List list() { + return bookRepository.findAll(); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/resources/application.properties b/persistence-modules/spring-boot-persistence/src/main/resources/application.properties index b0caf4a809..7b5a467a2b 100644 --- a/persistence-modules/spring-boot-persistence/src/main/resources/application.properties +++ b/persistence-modules/spring-boot-persistence/src/main/resources/application.properties @@ -3,3 +3,9 @@ spring.datasource.url = jdbc:hsqldb:mem:test;DB_CLOSE_DELAY=-1 spring.datasource.username = sa spring.datasource.password = spring.jpa.hibernate.ddl-auto = create + +# Enabling H2 Console +spring.h2.console.enabled=true + +# Uppercase Table Names +spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothibernate/application/tests/BookServiceUnitTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothibernate/application/tests/BookServiceUnitTest.java new file mode 100644 index 0000000000..fe8bb339a4 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothibernate/application/tests/BookServiceUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.springboothibernate.application.tests; + +import com.baeldung.springboothibernate.application.models.Book; +import com.baeldung.springboothibernate.application.services.BookService; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class BookServiceUnitTest { + + @Autowired + private BookService bookService; + + @Test + public void test() { + List books = bookService.list(); + + Assert.assertEquals(books.size(), 3); + } +} diff --git a/persistence-modules/spring-boot-persistence/src/test/resources/application.properties b/persistence-modules/spring-boot-persistence/src/test/resources/application.properties index a5c1d983cf..3a6470c8dc 100644 --- a/persistence-modules/spring-boot-persistence/src/test/resources/application.properties +++ b/persistence-modules/spring-boot-persistence/src/test/resources/application.properties @@ -12,5 +12,5 @@ hibernate.cache.use_second_level_cache=true hibernate.cache.use_query_cache=true hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory -spring.jpa.properties.hibernate.hbm2ddl.import_files=migrated_users.sql +spring.jpa.properties.hibernate.hbm2ddl.import_files=migrated_users.sql, import_books.sql spring.datasource.data=import_*_users.sql \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence/src/test/resources/import_books.sql b/persistence-modules/spring-boot-persistence/src/test/resources/import_books.sql new file mode 100644 index 0000000000..8eaf972a00 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/resources/import_books.sql @@ -0,0 +1,3 @@ +insert into book values(1, 'The Tartar Steppe'); +insert into book values(2, 'Poem Strip'); +insert into book values(3, 'Restless Nights: Selected Stories of Dino Buzzati'); \ No newline at end of file From ef9df7f56365ff2687f40b71c44641b8675ac956 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Mon, 11 Mar 2019 19:47:41 +0530 Subject: [PATCH 312/496] BAEL-10957 Moved jhipster project from heavy profile to default-first and integration-lite-first profiles --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3e739daf22..f672d1efce 100644 --- a/pom.xml +++ b/pom.xml @@ -456,6 +456,7 @@ jersey JGit jgroups + jhipster jib jjwt jmeter @@ -924,7 +925,6 @@ core-kotlin-2 jenkins/hello-world - jhipster jws libraries @@ -1091,6 +1091,7 @@ jersey JGit jgroups + jhipster jib jjwt jmeter @@ -1409,7 +1410,6 @@ core-kotlin-2 jenkins/hello-world - jhipster jws libraries From b10782f89ea9979e60ed5cf7e52fada6f5cc3fd0 Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Mon, 11 Mar 2019 11:49:16 -0300 Subject: [PATCH 313/496] Building a web application with Spring Boot and Angular (#6496) * Initial Commit * Delete angularclient folder * Add spring-boot-angular module to root pom.xml * Update pom.xml * Update root pom.xml * Update root pom.xml --- pom.xml | 2 + .../angularclient/.angular-cli.json | 0 .../baeldung => }/angularclient/.editorconfig | 0 .../baeldung => }/angularclient/.gitignore | 0 .../com/baeldung => }/angularclient/README.md | 0 .../angularclient/e2e/app.e2e-spec.ts | 0 .../baeldung => }/angularclient/e2e/app.po.ts | 0 .../angularclient/e2e/tsconfig.e2e.json | 0 .../baeldung => }/angularclient/karma.conf.js | 0 .../angularclient/package-lock.json | 0 .../baeldung => }/angularclient/package.json | 0 .../angularclient/protractor.conf.js | 0 .../src/app/app-routing.module.ts | 0 .../angularclient/src/app/app.component.css | 0 .../angularclient/src/app/app.component.html | 0 .../src/app/app.component.spec.ts | 0 .../angularclient/src/app/app.component.ts | 0 .../angularclient/src/app/app.module.ts | 0 .../angularclient/src/app/model/user.ts | 0 .../src/app/service/user.service.spec.ts | 0 .../src/app/service/user.service.ts | 0 .../src/app/user-form/user-form.component.css | 0 .../app/user-form/user-form.component.html | 0 .../app/user-form/user-form.component.spec.ts | 0 .../src/app/user-form/user-form.component.ts | 0 .../src/app/user-list/user-list.component.css | 0 .../app/user-list/user-list.component.html | 0 .../app/user-list/user-list.component.spec.ts | 0 .../src/app/user-list/user-list.component.ts | 0 .../angularclient/src/assets/.gitkeep | 0 .../src/environments/environment.prod.ts | 0 .../src/environments/environment.ts | 0 .../angularclient/src/favicon.ico | Bin .../angularclient/src/index.html | 0 .../baeldung => }/angularclient/src/main.ts | 0 .../angularclient/src/polyfills.ts | 0 .../angularclient/src/styles.css | 0 .../angularclient/src/tsconfig.app.json | 0 .../angularclient/src/tsconfig.spec.json | 0 .../angularclient/src/typings.d.ts | 0 .../baeldung => }/angularclient/tsconfig.json | 0 .../baeldung => }/angularclient/tslint.json | 0 .../controllers/UserController.java | 2 +- .../repositories/UserRepository.java | 1 - .../src/main/java/com/baeldung/pom.xml | 49 ++++++++++++++++++ 45 files changed, 52 insertions(+), 2 deletions(-) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/.angular-cli.json (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/.editorconfig (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/.gitignore (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/README.md (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/e2e/app.e2e-spec.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/e2e/app.po.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/e2e/tsconfig.e2e.json (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/karma.conf.js (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/package-lock.json (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/package.json (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/protractor.conf.js (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/app-routing.module.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/app.component.css (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/app.component.html (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/app.component.spec.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/app.component.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/app.module.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/model/user.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/service/user.service.spec.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/service/user.service.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/user-form/user-form.component.css (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/user-form/user-form.component.html (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/user-form/user-form.component.spec.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/user-form/user-form.component.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/user-list/user-list.component.css (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/user-list/user-list.component.html (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/user-list/user-list.component.spec.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/app/user-list/user-list.component.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/assets/.gitkeep (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/environments/environment.prod.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/environments/environment.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/favicon.ico (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/index.html (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/main.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/polyfills.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/styles.css (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/tsconfig.app.json (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/tsconfig.spec.json (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/src/typings.d.ts (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/tsconfig.json (100%) rename spring-boot-angular/{src/main/java/com/baeldung => }/angularclient/tslint.json (100%) create mode 100644 spring-boot-angular/src/main/java/com/baeldung/pom.xml diff --git a/pom.xml b/pom.xml index 3e739daf22..594fd47d51 100644 --- a/pom.xml +++ b/pom.xml @@ -587,6 +587,7 @@ spring-boot spring-boot-admin + spring-boot-angular spring-boot-angular-ecommerce spring-boot-autoconfiguration spring-boot-bootstrap @@ -1218,6 +1219,7 @@ spring-boot spring-boot-admin + spring-boot-angular spring-boot-angular-ecommerce spring-boot-autoconfiguration spring-boot-bootstrap diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/.angular-cli.json b/spring-boot-angular/angularclient/.angular-cli.json similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/.angular-cli.json rename to spring-boot-angular/angularclient/.angular-cli.json diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/.editorconfig b/spring-boot-angular/angularclient/.editorconfig similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/.editorconfig rename to spring-boot-angular/angularclient/.editorconfig diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/.gitignore b/spring-boot-angular/angularclient/.gitignore similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/.gitignore rename to spring-boot-angular/angularclient/.gitignore diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/README.md b/spring-boot-angular/angularclient/README.md similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/README.md rename to spring-boot-angular/angularclient/README.md diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.e2e-spec.ts b/spring-boot-angular/angularclient/e2e/app.e2e-spec.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.e2e-spec.ts rename to spring-boot-angular/angularclient/e2e/app.e2e-spec.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.po.ts b/spring-boot-angular/angularclient/e2e/app.po.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/app.po.ts rename to spring-boot-angular/angularclient/e2e/app.po.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/tsconfig.e2e.json b/spring-boot-angular/angularclient/e2e/tsconfig.e2e.json similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/e2e/tsconfig.e2e.json rename to spring-boot-angular/angularclient/e2e/tsconfig.e2e.json diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/karma.conf.js b/spring-boot-angular/angularclient/karma.conf.js similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/karma.conf.js rename to spring-boot-angular/angularclient/karma.conf.js diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/package-lock.json b/spring-boot-angular/angularclient/package-lock.json similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/package-lock.json rename to spring-boot-angular/angularclient/package-lock.json diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/package.json b/spring-boot-angular/angularclient/package.json similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/package.json rename to spring-boot-angular/angularclient/package.json diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/protractor.conf.js b/spring-boot-angular/angularclient/protractor.conf.js similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/protractor.conf.js rename to spring-boot-angular/angularclient/protractor.conf.js diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app-routing.module.ts b/spring-boot-angular/angularclient/src/app/app-routing.module.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app-routing.module.ts rename to spring-boot-angular/angularclient/src/app/app-routing.module.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.css b/spring-boot-angular/angularclient/src/app/app.component.css similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.css rename to spring-boot-angular/angularclient/src/app/app.component.css diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.html b/spring-boot-angular/angularclient/src/app/app.component.html similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.html rename to spring-boot-angular/angularclient/src/app/app.component.html diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.spec.ts b/spring-boot-angular/angularclient/src/app/app.component.spec.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.spec.ts rename to spring-boot-angular/angularclient/src/app/app.component.spec.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.ts b/spring-boot-angular/angularclient/src/app/app.component.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.component.ts rename to spring-boot-angular/angularclient/src/app/app.component.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.module.ts b/spring-boot-angular/angularclient/src/app/app.module.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/app.module.ts rename to spring-boot-angular/angularclient/src/app/app.module.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/model/user.ts b/spring-boot-angular/angularclient/src/app/model/user.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/model/user.ts rename to spring-boot-angular/angularclient/src/app/model/user.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.spec.ts b/spring-boot-angular/angularclient/src/app/service/user.service.spec.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.spec.ts rename to spring-boot-angular/angularclient/src/app/service/user.service.spec.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.ts b/spring-boot-angular/angularclient/src/app/service/user.service.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/service/user.service.ts rename to spring-boot-angular/angularclient/src/app/service/user.service.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.css b/spring-boot-angular/angularclient/src/app/user-form/user-form.component.css similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.css rename to spring-boot-angular/angularclient/src/app/user-form/user-form.component.css diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.html b/spring-boot-angular/angularclient/src/app/user-form/user-form.component.html similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.html rename to spring-boot-angular/angularclient/src/app/user-form/user-form.component.html diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.spec.ts b/spring-boot-angular/angularclient/src/app/user-form/user-form.component.spec.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.spec.ts rename to spring-boot-angular/angularclient/src/app/user-form/user-form.component.spec.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.ts b/spring-boot-angular/angularclient/src/app/user-form/user-form.component.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-form/user-form.component.ts rename to spring-boot-angular/angularclient/src/app/user-form/user-form.component.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.css b/spring-boot-angular/angularclient/src/app/user-list/user-list.component.css similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.css rename to spring-boot-angular/angularclient/src/app/user-list/user-list.component.css diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.html b/spring-boot-angular/angularclient/src/app/user-list/user-list.component.html similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.html rename to spring-boot-angular/angularclient/src/app/user-list/user-list.component.html diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.spec.ts b/spring-boot-angular/angularclient/src/app/user-list/user-list.component.spec.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.spec.ts rename to spring-boot-angular/angularclient/src/app/user-list/user-list.component.spec.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.ts b/spring-boot-angular/angularclient/src/app/user-list/user-list.component.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/app/user-list/user-list.component.ts rename to spring-boot-angular/angularclient/src/app/user-list/user-list.component.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/assets/.gitkeep b/spring-boot-angular/angularclient/src/assets/.gitkeep similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/assets/.gitkeep rename to spring-boot-angular/angularclient/src/assets/.gitkeep diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.prod.ts b/spring-boot-angular/angularclient/src/environments/environment.prod.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.prod.ts rename to spring-boot-angular/angularclient/src/environments/environment.prod.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.ts b/spring-boot-angular/angularclient/src/environments/environment.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/environments/environment.ts rename to spring-boot-angular/angularclient/src/environments/environment.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/favicon.ico b/spring-boot-angular/angularclient/src/favicon.ico similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/favicon.ico rename to spring-boot-angular/angularclient/src/favicon.ico diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/index.html b/spring-boot-angular/angularclient/src/index.html similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/index.html rename to spring-boot-angular/angularclient/src/index.html diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/main.ts b/spring-boot-angular/angularclient/src/main.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/main.ts rename to spring-boot-angular/angularclient/src/main.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/polyfills.ts b/spring-boot-angular/angularclient/src/polyfills.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/polyfills.ts rename to spring-boot-angular/angularclient/src/polyfills.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/styles.css b/spring-boot-angular/angularclient/src/styles.css similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/styles.css rename to spring-boot-angular/angularclient/src/styles.css diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.app.json b/spring-boot-angular/angularclient/src/tsconfig.app.json similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.app.json rename to spring-boot-angular/angularclient/src/tsconfig.app.json diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.spec.json b/spring-boot-angular/angularclient/src/tsconfig.spec.json similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/tsconfig.spec.json rename to spring-boot-angular/angularclient/src/tsconfig.spec.json diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/src/typings.d.ts b/spring-boot-angular/angularclient/src/typings.d.ts similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/src/typings.d.ts rename to spring-boot-angular/angularclient/src/typings.d.ts diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/tsconfig.json b/spring-boot-angular/angularclient/tsconfig.json similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/tsconfig.json rename to spring-boot-angular/angularclient/tsconfig.json diff --git a/spring-boot-angular/src/main/java/com/baeldung/angularclient/tslint.json b/spring-boot-angular/angularclient/tslint.json similarity index 100% rename from spring-boot-angular/src/main/java/com/baeldung/angularclient/tslint.json rename to spring-boot-angular/angularclient/tslint.json diff --git a/spring-boot-angular/src/main/java/com/baeldung/application/controllers/UserController.java b/spring-boot-angular/src/main/java/com/baeldung/application/controllers/UserController.java index c101ed771f..14c90d5b10 100644 --- a/spring-boot-angular/src/main/java/com/baeldung/application/controllers/UserController.java +++ b/spring-boot-angular/src/main/java/com/baeldung/application/controllers/UserController.java @@ -1,6 +1,6 @@ package com.baeldung.application.controllers; -import com.application.entities.User; +import com.baeldung.application.entities.User; import com.baeldung.application.repositories.UserRepository; import java.util.List; import org.springframework.web.bind.annotation.CrossOrigin; diff --git a/spring-boot-angular/src/main/java/com/baeldung/application/repositories/UserRepository.java b/spring-boot-angular/src/main/java/com/baeldung/application/repositories/UserRepository.java index f8ef5a4c0c..5a81cadcbe 100644 --- a/spring-boot-angular/src/main/java/com/baeldung/application/repositories/UserRepository.java +++ b/spring-boot-angular/src/main/java/com/baeldung/application/repositories/UserRepository.java @@ -6,5 +6,4 @@ import org.springframework.stereotype.Repository; import org.springframework.web.bind.annotation.CrossOrigin; @Repository -@CrossOrigin(origins = "http://localhost:4200") public interface UserRepository extends CrudRepository{} diff --git a/spring-boot-angular/src/main/java/com/baeldung/pom.xml b/spring-boot-angular/src/main/java/com/baeldung/pom.xml new file mode 100644 index 0000000000..d4ebc870b4 --- /dev/null +++ b/spring-boot-angular/src/main/java/com/baeldung/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + com.baeldung.springbootangular + spring-boot-angular + 1.0 + jar + Spring Boot Angular Application + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file From 9f2f10dfa2a9705ba052b21091e78bc771349252 Mon Sep 17 00:00:00 2001 From: TINO Date: Mon, 11 Mar 2019 22:23:46 +0300 Subject: [PATCH 314/496] BAEL - 1060 Review comments incorporated --- .../baeldung/rxjava/RxJavaHooksUnitTest.java | 410 +++++++++--------- 1 file changed, 193 insertions(+), 217 deletions(-) diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java b/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java index e31838448b..79b80f71ab 100644 --- a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java +++ b/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java @@ -1,5 +1,8 @@ package com.baeldung.rxjava; +import static org.junit.Assert.assertTrue; + +import org.junit.After; import org.junit.Test; import io.reactivex.Completable; @@ -14,316 +17,289 @@ import io.reactivex.schedulers.Schedulers; public class RxJavaHooksUnitTest { + private boolean initHookCalled = false; + private boolean hookCalled = false; + + @Test + public void givenObservable_whenError_shouldExecuteTheHook() { + RxJavaPlugins.setErrorHandler(throwable -> { + hookCalled = true; + }); + + Observable.error(new IllegalStateException()) + .subscribe(); + assertTrue(hookCalled); + } + @Test public void givenCompletable_whenAssembled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnCompletableAssembly(completable -> { - System.out.println("Assembling Completable"); - return completable; - }); - Completable.fromSingle(Single.just(1)); - } finally { - RxJavaPlugins.reset(); - } + + RxJavaPlugins.setOnCompletableAssembly(completable -> { + hookCalled = true; + return completable; + }); + Completable.fromSingle(Single.just(1)); + assertTrue(hookCalled); } @Test public void givenCompletable_whenSubscribed_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnCompletableSubscribe((completable, observer) -> { - System.out.println("Subscribing to Completable"); - return observer; - }); - Completable.fromSingle(Single.just(1)) - .test(true); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnCompletableSubscribe((completable, observer) -> { + hookCalled = true; + return observer; + }); + + Completable.fromSingle(Single.just(1)) + .test(); + assertTrue(hookCalled); } @Test public void givenObservable_whenAssembled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnObservableAssembly(observable -> { - System.out.println("Assembling Observable"); - return observable; - }); - Observable.range(1, 10); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnObservableAssembly(observable -> { + hookCalled = true; + return observable; + }); + + Observable.range(1, 10); + assertTrue(hookCalled); } @Test public void givenObservable_whenSubscribed_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnObservableSubscribe((observable, observer) -> { - System.out.println("Suscribing to Observable"); - return observer; - }); - Observable.range(1, 10) - .test(true); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnObservableSubscribe((observable, observer) -> { + hookCalled = true; + return observer; + }); + + Observable.range(1, 10) + .test(); + assertTrue(hookCalled); } @Test public void givenConnectableObservable_whenAssembled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnConnectableObservableAssembly(connectableObservable -> { - System.out.println("Assembling ConnectableObservable"); - return connectableObservable; - }); - ConnectableObservable.range(1, 10) - .publish() - .connect(); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnConnectableObservableAssembly(connectableObservable -> { + hookCalled = true; + return connectableObservable; + }); + + ConnectableObservable.range(1, 10) + .publish() + .connect(); + assertTrue(hookCalled); } @Test public void givenFlowable_whenAssembled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnFlowableAssembly(flowable -> { - System.out.println("Assembling Flowable"); - return flowable; - }); - Flowable.range(1, 10); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnFlowableAssembly(flowable -> { + hookCalled = true; + return flowable; + }); + + Flowable.range(1, 10); + assertTrue(hookCalled); } @Test public void givenFlowable_whenSubscribed_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnFlowableSubscribe((flowable, observer) -> { - System.out.println("Suscribing to Flowable"); - return observer; - }); - Flowable.range(1, 10) - .test(); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnFlowableSubscribe((flowable, observer) -> { + hookCalled = true; + return observer; + }); + + Flowable.range(1, 10) + .test(); + assertTrue(hookCalled); } @Test public void givenConnectableFlowable_whenAssembled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnConnectableFlowableAssembly(connectableFlowable -> { - System.out.println("Assembling ConnectableFlowable"); - return connectableFlowable; - }); - ConnectableFlowable.range(1, 10) - .publish() - .connect(); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnConnectableFlowableAssembly(connectableFlowable -> { + hookCalled = true; + return connectableFlowable; + }); + + ConnectableFlowable.range(1, 10) + .publish() + .connect(); + assertTrue(hookCalled); } @Test public void givenParallel_whenAssembled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnParallelAssembly(parallelFlowable -> { - System.out.println("Assembling ParallelFlowable"); - return parallelFlowable; - }); - Flowable.range(1, 10) - .parallel(); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnParallelAssembly(parallelFlowable -> { + hookCalled = true; + return parallelFlowable; + }); + + Flowable.range(1, 10) + .parallel(); + assertTrue(hookCalled); } @Test public void givenMaybe_whenAssembled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnMaybeAssembly(maybe -> { - System.out.println("Assembling Maybe"); - return maybe; - }); - Maybe.just(1); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnMaybeAssembly(maybe -> { + hookCalled = true; + return maybe; + }); + + Maybe.just(1); + assertTrue(hookCalled); } @Test public void givenMaybe_whenSubscribed_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnMaybeSubscribe((maybe, observer) -> { - System.out.println("Suscribing to Maybe"); - return observer; - }); - Maybe.just(1) - .test(); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnMaybeSubscribe((maybe, observer) -> { + hookCalled = true; + return observer; + }); + + Maybe.just(1) + .test(); + assertTrue(hookCalled); } @Test public void givenSingle_whenAssembled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnSingleAssembly(single -> { - System.out.println("Assembling Single"); - return single; - }); - Single.just(1); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setOnSingleAssembly(single -> { + hookCalled = true; + return single; + }); + + Single.just(1); + assertTrue(hookCalled); } @Test public void givenSingle_whenSubscribed_shouldExecuteTheHook() { - try { - RxJavaPlugins.setOnSingleSubscribe((single, observer) -> { - System.out.println("Suscribing to Single"); - return observer; - }); + RxJavaPlugins.setOnSingleSubscribe((single, observer) -> { + hookCalled = true; + return observer; + }); - Single.just(1) - .test(); - } finally { - RxJavaPlugins.reset(); - } + Single.just(1) + .test(); + assertTrue(hookCalled); } @Test public void givenAnyScheduler_whenCalled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setScheduleHandler((runnable) -> { - System.out.println("Executing Scheduler"); - return runnable; - }); - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.single()) - .test(); + RxJavaPlugins.setScheduleHandler((runnable) -> { + hookCalled = true; + return runnable; + }); - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.computation()) - .test(); - } finally { - RxJavaPlugins.reset(); - } + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.single()) + .test(); + hookCalled = false; + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.computation()) + .test(); + assertTrue(hookCalled); } @Test public void givenComputationScheduler_whenCalled_shouldExecuteTheHooks() { - try { - RxJavaPlugins.setInitComputationSchedulerHandler((scheduler) -> { - System.out.println("Initializing Computation Scheduler"); - return scheduler.call(); - }); - RxJavaPlugins.setComputationSchedulerHandler((scheduler) -> { - System.out.println("Executing Computation Scheduler"); - return scheduler; - }); - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.computation()) - .test(); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setInitComputationSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); + RxJavaPlugins.setComputationSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.computation()) + .test(); + assertTrue(hookCalled && initHookCalled); } @Test public void givenIOScheduler_whenCalled_shouldExecuteTheHooks() { - try { - RxJavaPlugins.setInitIoSchedulerHandler((scheduler) -> { - System.out.println("Initializing IO Scheduler"); - return scheduler.call(); - }); - RxJavaPlugins.setIoSchedulerHandler((scheduler) -> { - System.out.println("Executing IO Scheduler"); - return scheduler; - }); + RxJavaPlugins.setInitIoSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.io()) - .test(); - } finally { - RxJavaPlugins.reset(); - } + RxJavaPlugins.setIoSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.io()) + .test(); + assertTrue(hookCalled && initHookCalled); } @Test public void givenNewThreadScheduler_whenCalled_shouldExecuteTheHook() { - try { - RxJavaPlugins.setInitNewThreadSchedulerHandler((scheduler) -> { - System.out.println("Initializing newThread Scheduler"); - return scheduler.call(); - }); - RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> { - System.out.println("Executing newThread Scheduler"); - return scheduler; - }); + RxJavaPlugins.setInitNewThreadSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); - Observable.range(1, 15) - .map(v -> v * 2) - .subscribeOn(Schedulers.newThread()) - .test(); + RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); - } finally { - RxJavaPlugins.reset(); - } + Observable.range(1, 15) + .map(v -> v * 2) + .subscribeOn(Schedulers.newThread()) + .test(); + assertTrue(hookCalled && initHookCalled); } @Test public void givenSingleScheduler_whenCalled_shouldExecuteTheHooks() { - try { - RxJavaPlugins.setInitSingleSchedulerHandler((scheduler) -> { - System.out.println("Initializing Single Scheduler"); - return scheduler.call(); - }); - RxJavaPlugins.setSingleSchedulerHandler((scheduler) -> { - System.out.println("Executing Single Scheduler"); - return scheduler; - }); - - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.single()) - .test(); - - } finally { - RxJavaPlugins.reset(); - } - } - - @Test - public void givenObservable_whenError_shouldExecuteTheHook() { - RxJavaPlugins.setErrorHandler(throwable -> { - System.out.println("Handling error" + throwable.getCause()); + RxJavaPlugins.setInitSingleSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); }); - Observable.error(new IllegalStateException()) - .subscribe(); + RxJavaPlugins.setSingleSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.single()) + .test(); + assertTrue(hookCalled && initHookCalled); + + } + + @After + public void reset() { + initHookCalled = false; + hookCalled = false; + RxJavaPlugins.reset(); } } From 63b652270afcd5a09a0d21ac4eb175df1424e5a8 Mon Sep 17 00:00:00 2001 From: Loredana Date: Mon, 11 Mar 2019 23:02:10 +0200 Subject: [PATCH 315/496] add new core-java-os module --- core-java-9/README.md | 2 - core-java-os/.gitignore | 26 ++++++ core-java-os/README.md | 8 ++ core-java-os/pom.xml | 82 +++++++++++++++++++ .../baeldung/java9/process/ChildProcess.java | 0 .../java9/process/OutputStreamExample.java | 0 .../process/ProcessCompilationError.java | 2 +- .../java9/process/ProcessUnderstanding.java | 0 .../baeldung/java9/process/ProcessUtils.java | 0 .../baeldung/java9/process/ServiceMain.java | 0 core-java-os/src/main/resources/logback.xml | 13 +++ .../ProcessAPIEnhancementsUnitTest.java | 16 ++-- .../java9/process/ProcessApiUnitTest.java | 14 ++-- .../process/ProcessUnderstandingUnitTest.java | 2 +- .../ProcessBuilderUnitTest.java | 0 core-java-os/src/test/resources/.gitignore | 13 +++ pom.xml | 2 + 17 files changed, 161 insertions(+), 19 deletions(-) create mode 100644 core-java-os/.gitignore create mode 100644 core-java-os/README.md create mode 100644 core-java-os/pom.xml rename {core-java-9 => core-java-os}/src/main/java/com/baeldung/java9/process/ChildProcess.java (100%) rename {core-java-9 => core-java-os}/src/main/java/com/baeldung/java9/process/OutputStreamExample.java (100%) rename {core-java-9 => core-java-os}/src/main/java/com/baeldung/java9/process/ProcessCompilationError.java (87%) rename {core-java-9 => core-java-os}/src/main/java/com/baeldung/java9/process/ProcessUnderstanding.java (100%) rename {core-java-9 => core-java-os}/src/main/java/com/baeldung/java9/process/ProcessUtils.java (100%) rename {core-java-9 => core-java-os}/src/main/java/com/baeldung/java9/process/ServiceMain.java (100%) create mode 100644 core-java-os/src/main/resources/logback.xml rename {core-java-9 => core-java-os}/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java (89%) rename {core-java-9 => core-java-os}/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java (85%) rename core-java-9/src/test/java/com/baeldung/java9/process/ProcessUnderstandingTest.java => core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java (99%) rename {core-java-9 => core-java-os}/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java (100%) create mode 100644 core-java-os/src/test/resources/.gitignore diff --git a/core-java-9/README.md b/core-java-9/README.md index 224306db19..fb7f69dc42 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -9,7 +9,6 @@ - [Java 9 Convenience Factory Methods for Collections](http://www.baeldung.com/java-9-collections-factory-methods) - [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors) - [Java 9 CompletableFuture API Improvements](http://www.baeldung.com/java-9-completablefuture) -- [Java 9 Process API Improvements](http://www.baeldung.com/java-9-process-api) - [Introduction to Java 9 StackWalking API](http://www.baeldung.com/java-9-stackwalking-api) - [Introduction to Project Jigsaw](http://www.baeldung.com/project-jigsaw-java-modularity) - [Java 9 Optional API Additions](http://www.baeldung.com/java-9-optional) @@ -25,7 +24,6 @@ - [Iterate Through a Range of Dates in Java](https://www.baeldung.com/java-iterate-date-range) - [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) - [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api) -- [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) - [Immutable Set in Java](https://www.baeldung.com/java-immutable-set) - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) - [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation) diff --git a/core-java-os/.gitignore b/core-java-os/.gitignore new file mode 100644 index 0000000000..3de4cc647e --- /dev/null +++ b/core-java-os/.gitignore @@ -0,0 +1,26 @@ +*.class + +0.* + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* +.resourceCache + +# Packaged files # +*.jar +*.war +*.ear + +# Files generated by integration tests +*.txt +backup-pom.xml +/bin/ +/temp + +#IntelliJ specific +.idea/ +*.iml \ No newline at end of file diff --git a/core-java-os/README.md b/core-java-os/README.md new file mode 100644 index 0000000000..90e1d29a58 --- /dev/null +++ b/core-java-os/README.md @@ -0,0 +1,8 @@ +========= + +This module uses Java 9, so make sure to have the JDK 9 installed to run it. + +## +### Relevant Articles: +- [Java 9 Process API Improvements](http://www.baeldung.com/java-9-process-api) +- [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) diff --git a/core-java-os/pom.xml b/core-java-os/pom.xml new file mode 100644 index 0000000000..c9097cb554 --- /dev/null +++ b/core-java-os/pom.xml @@ -0,0 +1,82 @@ + + 4.0.0 + com.baeldung + core-java-os + 0.1.0-SNAPSHOT + core-java-os + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + commons-io + commons-io + ${commons-io.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + log4j + log4j + ${log4j.version} + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + core-java-os + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + + 3.5 + 4.1 + 4.01 + + + 3.6.1 + 1.8.9 + 1.9 + 1.9 + 25.1-jre + + diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ChildProcess.java b/core-java-os/src/main/java/com/baeldung/java9/process/ChildProcess.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/process/ChildProcess.java rename to core-java-os/src/main/java/com/baeldung/java9/process/ChildProcess.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/OutputStreamExample.java b/core-java-os/src/main/java/com/baeldung/java9/process/OutputStreamExample.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/process/OutputStreamExample.java rename to core-java-os/src/main/java/com/baeldung/java9/process/OutputStreamExample.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ProcessCompilationError.java b/core-java-os/src/main/java/com/baeldung/java9/process/ProcessCompilationError.java similarity index 87% rename from core-java-9/src/main/java/com/baeldung/java9/process/ProcessCompilationError.java rename to core-java-os/src/main/java/com/baeldung/java9/process/ProcessCompilationError.java index 8b6ae0b441..73eacddc4c 100644 --- a/core-java-9/src/main/java/com/baeldung/java9/process/ProcessCompilationError.java +++ b/core-java-os/src/main/java/com/baeldung/java9/process/ProcessCompilationError.java @@ -3,5 +3,5 @@ package com.baeldung.java9.process; public class ProcessCompilationError { //This method has been written to generate error to display //how process errorStream() can consume error - public static void(); + //public static void(); } diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ProcessUnderstanding.java b/core-java-os/src/main/java/com/baeldung/java9/process/ProcessUnderstanding.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/process/ProcessUnderstanding.java rename to core-java-os/src/main/java/com/baeldung/java9/process/ProcessUnderstanding.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java b/core-java-os/src/main/java/com/baeldung/java9/process/ProcessUtils.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/process/ProcessUtils.java rename to core-java-os/src/main/java/com/baeldung/java9/process/ProcessUtils.java diff --git a/core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java b/core-java-os/src/main/java/com/baeldung/java9/process/ServiceMain.java similarity index 100% rename from core-java-9/src/main/java/com/baeldung/java9/process/ServiceMain.java rename to core-java-os/src/main/java/com/baeldung/java9/process/ServiceMain.java diff --git a/core-java-os/src/main/resources/logback.xml b/core-java-os/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/core-java-os/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java b/core-java-os/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java similarity index 89% rename from core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java rename to core-java-os/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java index 9a227a9c8f..8cefceef1d 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java +++ b/core-java-os/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java @@ -18,13 +18,13 @@ import org.slf4j.LoggerFactory; public class ProcessAPIEnhancementsUnitTest { - Logger log = LoggerFactory.getLogger(ProcessAPIEnhancementsTest.class); + Logger log = LoggerFactory.getLogger(ProcessAPIEnhancementsUnitTest.class); @Test public void givenCurrentProcess_whenInvokeGetInfo_thenSuccess() throws IOException { ProcessHandle processHandle = ProcessHandle.current(); ProcessHandle.Info processInfo = processHandle.info(); - assertNotNull(processHandle.getPid()); + assertNotNull(processHandle.pid()); assertEquals(false, processInfo.arguments() .isPresent()); assertEquals(true, processInfo.command() @@ -51,7 +51,7 @@ public class ProcessAPIEnhancementsUnitTest { .start(); ProcessHandle processHandle = process.toHandle(); ProcessHandle.Info processInfo = processHandle.info(); - assertNotNull(processHandle.getPid()); + assertNotNull(processHandle.pid()); assertEquals(false, processInfo.arguments() .isPresent()); assertEquals(true, processInfo.command() @@ -72,7 +72,7 @@ public class ProcessAPIEnhancementsUnitTest { Stream liveProcesses = ProcessHandle.allProcesses(); liveProcesses.filter(ProcessHandle::isAlive) .forEach(ph -> { - assertNotNull(ph.getPid()); + assertNotNull(ph.pid()); assertEquals(true, ph.info() .command() .isPresent()); @@ -102,12 +102,12 @@ public class ProcessAPIEnhancementsUnitTest { Stream children = ProcessHandle.current() .children(); children.filter(ProcessHandle::isAlive) - .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.getPid(), ph.info() + .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.pid(), ph.info() .command())); Stream descendants = ProcessHandle.current() .descendants(); descendants.filter(ProcessHandle::isAlive) - .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.getPid(), ph.info() + .forEach(ph -> log.info("PID: {}, Cmd: {}", ph.pid(), ph.info() .command())); } @@ -121,12 +121,12 @@ public class ProcessAPIEnhancementsUnitTest { .start(); ProcessHandle processHandle = process.toHandle(); - log.info("PID: {} has started", processHandle.getPid()); + log.info("PID: {} has started", processHandle.pid()); CompletableFuture onProcessExit = processHandle.onExit(); onProcessExit.get(); assertEquals(false, processHandle.isAlive()); onProcessExit.thenAccept(ph -> { - log.info("PID: {} has stopped", ph.getPid()); + log.info("PID: {} has stopped", ph.pid()); }); } diff --git a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java b/core-java-os/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java similarity index 85% rename from core-java-9/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java rename to core-java-os/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java index e125f10da7..8bdf8cb09f 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java +++ b/core-java-os/src/test/java/com/baeldung/java9/process/ProcessApiUnitTest.java @@ -30,7 +30,7 @@ public class ProcessApiUnitTest { @Test public void processInfoExample() throws NoSuchAlgorithmException { ProcessHandle self = ProcessHandle.current(); - long PID = self.getPid(); + long PID = self.pid(); ProcessHandle.Info procInfo = self.info(); Optional args = procInfo.arguments(); Optional cmd = procInfo.commandLine(); @@ -45,7 +45,7 @@ public class ProcessApiUnitTest { Stream allProc = ProcessHandle.current().children(); allProc.forEach(p -> { - System.out.println("Proc " + p.getPid()); + System.out.println("Proc " + p.pid()); }); } @@ -54,7 +54,7 @@ public class ProcessApiUnitTest { public void createAndDestroyProcess() throws IOException, InterruptedException { int numberOfChildProcesses = 5; for (int i = 0; i < numberOfChildProcesses; i++) { - createNewJVM(ServiceMain.class, i).getPid(); + createNewJVM(ServiceMain.class, i).pid(); } Stream childProc = ProcessHandle.current().children(); @@ -62,10 +62,10 @@ public class ProcessApiUnitTest { childProc = ProcessHandle.current().children(); childProc.forEach(processHandle -> { - assertTrue("Process " + processHandle.getPid() + " should be alive!", processHandle.isAlive()); + assertTrue("Process " + processHandle.pid() + " should be alive!", processHandle.isAlive()); CompletableFuture onProcExit = processHandle.onExit(); onProcExit.thenAccept(procHandle -> { - System.out.println("Process with PID " + procHandle.getPid() + " has stopped"); + System.out.println("Process with PID " + procHandle.pid() + " has stopped"); }); }); @@ -73,14 +73,14 @@ public class ProcessApiUnitTest { childProc = ProcessHandle.current().children(); childProc.forEach(procHandle -> { - assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy()); + assertTrue("Could not kill process " + procHandle.pid(), procHandle.destroy()); }); Thread.sleep(5000); childProc = ProcessHandle.current().children(); childProc.forEach(procHandle -> { - assertFalse("Process " + procHandle.getPid() + " should not be alive!", procHandle.isAlive()); + assertFalse("Process " + procHandle.pid() + " should not be alive!", procHandle.isAlive()); }); } diff --git a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessUnderstandingTest.java b/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java similarity index 99% rename from core-java-9/src/test/java/com/baeldung/java9/process/ProcessUnderstandingTest.java rename to core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java index 2c5525b9ed..6ad07c5c3a 100644 --- a/core-java-9/src/test/java/com/baeldung/java9/process/ProcessUnderstandingTest.java +++ b/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java @@ -14,7 +14,7 @@ import java.lang.Integer; import org.junit.jupiter.api.Test; -class ProcessUnderstandingTest { +class ProcessUnderstandingUnitTest { @Test public void givenSourceProgram_whenExecutedFromAnotherProgram_thenSourceProgramOutput3() throws IOException { diff --git a/core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java b/core-java-os/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java similarity index 100% rename from core-java-9/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java rename to core-java-os/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java diff --git a/core-java-os/src/test/resources/.gitignore b/core-java-os/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/core-java-os/src/test/resources/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/pom.xml b/pom.xml index 3e739daf22..e9aef8bf35 100644 --- a/pom.xml +++ b/pom.xml @@ -379,6 +379,7 @@ core-java-8 + core-java-arrays core-java-collections core-java-collections-list @@ -1015,6 +1016,7 @@ core-java-8 + core-java-arrays core-java-collections core-java-collections-list From 4a0810acc8ce940488c692b1c41a27be89329881 Mon Sep 17 00:00:00 2001 From: Surapaneni Venkata Kiran Date: Mon, 11 Mar 2019 23:49:24 -0400 Subject: [PATCH 316/496] BAEL-2575 : Disable auto configuration of data source (#6513) --- .../disabledatasource/application/Application.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/disabledatasource/application/Application.java diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/disabledatasource/application/Application.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/disabledatasource/application/Application.java new file mode 100644 index 0000000000..79273ba141 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/disabledatasource/application/Application.java @@ -0,0 +1,13 @@ +package com.baeldung.disabledatasource.application; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +@SpringBootApplication(exclude=DataSourceAutoConfiguration.class) +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} From 51cc4612750c2ec51c4538f1b26482285cb868ee Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Tue, 12 Mar 2019 15:30:51 +0800 Subject: [PATCH 317/496] Update README.md --- persistence-modules/hibernate-ogm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/hibernate-ogm/README.md b/persistence-modules/hibernate-ogm/README.md index 508aa77b03..df99cce129 100644 --- a/persistence-modules/hibernate-ogm/README.md +++ b/persistence-modules/hibernate-ogm/README.md @@ -1,4 +1,4 @@ ## Relevant articles: -- [Guide to Hibernate OGM](https://www.baeldung.com/hibernate-ogm) +- [A Guide to Hibernate OGM](https://www.baeldung.com/hibernate-ogm) From 527e3440acfae883ded0bca0c47ae0a7ca0460a6 Mon Sep 17 00:00:00 2001 From: Sumeet Gajbhar Date: Tue, 12 Mar 2019 22:11:02 +0530 Subject: [PATCH 318/496] BAEL-2520 code moved to java-jpa module (#6525) * BAEL-2520 code changes done * BAEL-2520 moved code to java-jpa module * BAEL-2520 moved code to java-jpa module --- .../baeldung/jpa/criteria/entity/Item.java | 49 +++++ .../repository/CustomItemRepository.java | 12 ++ .../impl/CustomItemRepositoryImpl.java | 77 +++++++ .../main/resources/META-INF/persistence.xml | 201 ++++++++++-------- .../CustomItemRepositoryIntegrationTest.java | 44 ++++ .../java-jpa/src/test/resources/item.sql | 4 + .../repositories/CustomItemRepository.java | 5 - .../impl/CustomItemRepositoryImpl.java | 55 ----- .../CustomItemRepositoryIntegrationTest.java | 94 -------- 9 files changed, 297 insertions(+), 244 deletions(-) create mode 100644 persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/entity/Item.java create mode 100644 persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/repository/CustomItemRepository.java create mode 100644 persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/repository/impl/CustomItemRepositoryImpl.java create mode 100644 persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/criteria/repository/impl/CustomItemRepositoryIntegrationTest.java create mode 100644 persistence-modules/java-jpa/src/test/resources/item.sql delete mode 100644 persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryIntegrationTest.java diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/entity/Item.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/entity/Item.java new file mode 100644 index 0000000000..64ef46f265 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/entity/Item.java @@ -0,0 +1,49 @@ +package com.baeldung.jpa.criteria.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Table(name = "item") +@Entity +public class Item { + + @Id + private Long id; + private String color; + private String grade; + private String name; + + public String getColor() { + return color; + } + + public String getGrade() { + return grade; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setColor(String color) { + this.color = color; + } + + public void setGrade(String grade) { + this.grade = grade; + } + + public void setId(Long id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/repository/CustomItemRepository.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/repository/CustomItemRepository.java new file mode 100644 index 0000000000..c55dc4a592 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/repository/CustomItemRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.jpa.criteria.repository; + +import java.util.List; + +import com.baeldung.jpa.criteria.entity.Item; + +public interface CustomItemRepository { + + List findItemsByColorAndGrade(); + + List findItemByColorOrGrade(); +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/repository/impl/CustomItemRepositoryImpl.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/repository/impl/CustomItemRepositoryImpl.java new file mode 100644 index 0000000000..bf1d3eed0b --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/criteria/repository/impl/CustomItemRepositoryImpl.java @@ -0,0 +1,77 @@ +package com.baeldung.jpa.criteria.repository.impl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import com.baeldung.jpa.criteria.entity.Item; +import com.baeldung.jpa.criteria.repository.CustomItemRepository; + +public class CustomItemRepositoryImpl implements CustomItemRepository { + + private EntityManager entityManager; + + public CustomItemRepositoryImpl() { + super(); + EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-h2-criteria"); + entityManager = factory.createEntityManager(); + } + + @Override + public List findItemsByColorAndGrade() { + + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Item.class); + Root itemRoot = criteriaQuery.from(Item.class); + + Predicate predicateForBlueColor = criteriaBuilder.equal(itemRoot.get("color"), "blue"); + Predicate predicateForRedColor = criteriaBuilder.equal(itemRoot.get("color"), "red"); + Predicate predicateForColor = criteriaBuilder.or(predicateForBlueColor, predicateForRedColor); + + Predicate predicateForGradeA = criteriaBuilder.equal(itemRoot.get("grade"), "A"); + Predicate predicateForGradeB = criteriaBuilder.equal(itemRoot.get("grade"), "B"); + Predicate predicateForGrade = criteriaBuilder.or(predicateForGradeA, predicateForGradeB); + + // final search filter + Predicate finalPredicate = criteriaBuilder.and(predicateForColor, predicateForGrade); + + criteriaQuery.where(finalPredicate); + + List items = entityManager.createQuery(criteriaQuery) + .getResultList(); + return items; + } + + @Override + public List findItemByColorOrGrade() { + + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Item.class); + Root itemRoot = criteriaQuery.from(Item.class); + + Predicate predicateForBlueColor = criteriaBuilder.equal(itemRoot.get("color"), "red"); + Predicate predicateForGradeA = criteriaBuilder.equal(itemRoot.get("grade"), "D"); + Predicate predicateForBlueColorAndGradeA = criteriaBuilder.and(predicateForBlueColor, predicateForGradeA); + + Predicate predicateForRedColor = criteriaBuilder.equal(itemRoot.get("color"), "blue"); + Predicate predicateForGradeB = criteriaBuilder.equal(itemRoot.get("grade"), "B"); + Predicate predicateForRedColorAndGradeB = criteriaBuilder.and(predicateForRedColor, predicateForGradeB); + + // final search filter + Predicate finalPredicate = criteriaBuilder.or(predicateForBlueColorAndGradeA, predicateForRedColorAndGradeB); + + criteriaQuery.where(finalPredicate); + + List items = entityManager.createQuery(criteriaQuery) + .getResultList(); + return items; + } +} diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml index 8592fce533..6382f329c1 100644 --- a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml @@ -1,91 +1,112 @@ - - - - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.sqlresultsetmapping.ScheduledDay - com.baeldung.sqlresultsetmapping.Employee - true - - - - - - - - - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.stringcast.Message - true - - - - - - - - - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.model.Car - true - - - - - - - - - - - - com.baeldung.jpa.entitygraph.model.Post - com.baeldung.jpa.entitygraph.model.User - com.baeldung.jpa.entitygraph.model.Comment - true - - - - - - - - - - - - - org.eclipse.persistence.jpa.PersistenceProvider - com.baeldung.jpa.datetime.JPA22DateTimeEntity - true - - - - - - - - - - - - - - + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.sqlresultsetmapping.ScheduledDay + com.baeldung.sqlresultsetmapping.Employee + true + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.stringcast.Message + true + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.model.Car + true + + + + + + + + + + + + com.baeldung.jpa.entitygraph.model.Post + com.baeldung.jpa.entitygraph.model.User + com.baeldung.jpa.entitygraph.model.Comment + true + + + + + + + + + + + + + org.eclipse.persistence.jpa.PersistenceProvider + com.baeldung.jpa.datetime.JPA22DateTimeEntity + true + + + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.criteria.entity.Item + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/criteria/repository/impl/CustomItemRepositoryIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/criteria/repository/impl/CustomItemRepositoryIntegrationTest.java new file mode 100644 index 0000000000..169fb44618 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/criteria/repository/impl/CustomItemRepositoryIntegrationTest.java @@ -0,0 +1,44 @@ +package com.baeldung.jpa.criteria.repository.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.util.List; + +import org.junit.Test; + +import com.baeldung.jpa.criteria.entity.Item; +import com.baeldung.jpa.criteria.repository.CustomItemRepository; + +public class CustomItemRepositoryIntegrationTest { + + CustomItemRepository customItemRepository = new CustomItemRepositoryImpl(); + + @Test + public void givenItems_whenFindItemsByColorAndGrade_thenReturnItems() { + + List items = customItemRepository.findItemsByColorAndGrade(); + + assertFalse("No items found", items.isEmpty()); + assertEquals("There should be only one item", 1, items.size()); + + Item item = items.get(0); + + assertEquals("this item do not have blue color", "blue", item.getColor()); + assertEquals("this item does not belong to A grade", "A", item.getGrade()); + } + + @Test + public void givenItems_whenFindItemByColorOrGrade_thenReturnItems() { + + List items = customItemRepository.findItemByColorOrGrade(); + + assertFalse("No items found", items.isEmpty()); + assertEquals("There should be only one item", 1, items.size()); + + Item item = items.get(0); + + assertEquals("this item do not have red color", "red", item.getColor()); + assertEquals("this item does not belong to D grade", "D", item.getGrade()); + } +} diff --git a/persistence-modules/java-jpa/src/test/resources/item.sql b/persistence-modules/java-jpa/src/test/resources/item.sql new file mode 100644 index 0000000000..faf50f6829 --- /dev/null +++ b/persistence-modules/java-jpa/src/test/resources/item.sql @@ -0,0 +1,4 @@ +insert into item(id,grade,color) values (10,'C','blue'); +insert into item(id,grade,color) values (11,'C','red'); +insert into item(id,grade,color) values (12,'A','blue'); +insert into item(id,grade,color) values (13,'D','red'); \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemRepository.java index 4299f9e3bb..f5b94e507c 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/CustomItemRepository.java @@ -1,7 +1,5 @@ package com.baeldung.dao.repositories; -import java.util.List; - import org.springframework.stereotype.Repository; import com.baeldung.domain.Item; @@ -15,7 +13,4 @@ public interface CustomItemRepository { void findThenDelete(Long id); - List findItemsByColorAndGrade(); - - List findItemByColorOrGrade(); } diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryImpl.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryImpl.java index 9791cb0aa7..5538448c49 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryImpl.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryImpl.java @@ -1,12 +1,6 @@ package com.baeldung.dao.repositories.impl; -import java.util.List; - import javax.persistence.EntityManager; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; @@ -36,53 +30,4 @@ public class CustomItemRepositoryImpl implements CustomItemRepository { entityManager.remove(item); } - @Override - public List findItemsByColorAndGrade() { - - CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); - CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Item.class); - Root itemRoot = criteriaQuery.from(Item.class); - - Predicate predicateForBlueColor = criteriaBuilder.equal(itemRoot.get("color"), "blue"); - Predicate predicateForRedColor = criteriaBuilder.equal(itemRoot.get("color"), "red"); - Predicate predicateForColor = criteriaBuilder.or(predicateForBlueColor, predicateForRedColor); - - Predicate predicateForGradeA = criteriaBuilder.equal(itemRoot.get("grade"), "A"); - Predicate predicateForGradeB = criteriaBuilder.equal(itemRoot.get("grade"), "B"); - Predicate predicateForGrade = criteriaBuilder.or(predicateForGradeA, predicateForGradeB); - - // final search filter - Predicate finalPredicate = criteriaBuilder.and(predicateForColor, predicateForGrade); - - criteriaQuery.where(finalPredicate); - - List items = entityManager.createQuery(criteriaQuery) - .getResultList(); - return items; - } - - @Override - public List findItemByColorOrGrade() { - - CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); - CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Item.class); - Root itemRoot = criteriaQuery.from(Item.class); - - Predicate predicateForBlueColor = criteriaBuilder.equal(itemRoot.get("color"), "red"); - Predicate predicateForGradeA = criteriaBuilder.equal(itemRoot.get("grade"), "D"); - Predicate predicateForBlueColorAndGradeA = criteriaBuilder.and(predicateForBlueColor, predicateForGradeA); - - Predicate predicateForRedColor = criteriaBuilder.equal(itemRoot.get("color"), "blue"); - Predicate predicateForGradeB = criteriaBuilder.equal(itemRoot.get("grade"), "B"); - Predicate predicateForRedColorAndGradeB = criteriaBuilder.and(predicateForRedColor, predicateForGradeB); - - // final search filter - Predicate finalPredicate = criteriaBuilder.or(predicateForBlueColorAndGradeA, predicateForRedColorAndGradeB); - - criteriaQuery.where(finalPredicate); - - List items = entityManager.createQuery(criteriaQuery) - .getResultList(); - return items; - } } diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryIntegrationTest.java deleted file mode 100644 index c5fb7fa25f..0000000000 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/impl/CustomItemRepositoryIntegrationTest.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.baeldung.dao.repositories.impl; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import java.util.List; - -import javax.persistence.EntityManager; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.CollectionUtils; - -import com.baeldung.config.PersistenceConfiguration; -import com.baeldung.config.PersistenceProductConfiguration; -import com.baeldung.config.PersistenceUserConfiguration; -import com.baeldung.dao.repositories.CustomItemRepository; -import com.baeldung.domain.Item; - -@RunWith(SpringRunner.class) -@DataJpaTest(excludeAutoConfiguration = { PersistenceConfiguration.class, PersistenceUserConfiguration.class, PersistenceProductConfiguration.class }) -public class CustomItemRepositoryIntegrationTest { - - @Autowired - CustomItemRepository customItemRepositoryImpl; - - @Autowired - EntityManager entityManager; - - @Before - public void setUp() { - - Item firstItem = new Item(); - firstItem.setColor("blue"); - firstItem.setGrade("C"); - firstItem.setId(10l); - - entityManager.persist(firstItem); - - Item secondItem = new Item(); - secondItem.setColor("red"); - secondItem.setGrade("C"); - secondItem.setId(11l); - - entityManager.persist(secondItem); - - Item thirdItem = new Item(); - thirdItem.setColor("blue"); - thirdItem.setGrade("A"); - thirdItem.setId(12l); - - entityManager.persist(thirdItem); - - Item fourthItem = new Item(); - fourthItem.setColor("red"); - fourthItem.setGrade("D"); - fourthItem.setId(13l); - - entityManager.persist(fourthItem); - } - - @Test - public void givenItems_whenFindItemsByColorAndGrade_thenReturnItems() { - - List items = customItemRepositoryImpl.findItemsByColorAndGrade(); - - assertFalse("No items found", CollectionUtils.isEmpty(items)); - assertEquals("There should be only one item", 1, items.size()); - - Item item = items.get(0); - - assertEquals("this item do not have blue color", "blue", item.getColor()); - assertEquals("this item does not belong to A grade", "A", item.getGrade()); - } - - @Test - public void givenItems_whenFindItemByColorOrGrade_thenReturnItems() { - - List items = customItemRepositoryImpl.findItemByColorOrGrade(); - - assertFalse("No items found", CollectionUtils.isEmpty(items)); - assertEquals("There should be only one item", 1, items.size()); - - Item item = items.get(0); - - assertEquals("this item do not have red color", "red", item.getColor()); - assertEquals("this item does not belong to D grade", "D", item.getGrade()); - } - -} From b7cc946a3297e188de0fb0e77d8bc3ba33cf57da Mon Sep 17 00:00:00 2001 From: isaolmez Date: Tue, 12 Mar 2019 22:35:27 +0300 Subject: [PATCH 319/496] BAEL-2715: Added code samples for Netty server configuration --- pom.xml | 1 + spring-5-reactive-netty/.gitignore | 11 ++++ spring-5-reactive-netty/README.md | 3 ++ spring-5-reactive-netty/pom.xml | 51 ++++++++++++++++++ .../serverconfig/ServerConfigApplication.java | 16 ++++++ .../client/GreetingWebClient.java | 37 +++++++++++++ .../server/GreetingController.java | 23 ++++++++ .../serverconfig/server/GreetingService.java | 12 +++++ .../NettyWebServerFactoryPortCustomizer.java | 31 +++++++++++ .../NettyWebServerFactorySslCustomizer.java | 23 ++++++++ .../src/main/resources/logback.xml | 31 +++++++++++ .../src/main/resources/sample.jks | Bin 0 -> 2264 bytes .../GreetingControllerIntegrationTest.java | 41 ++++++++++++++ .../src/test/resources/logback-test.xml | 13 +++++ 14 files changed, 293 insertions(+) create mode 100644 spring-5-reactive-netty/.gitignore create mode 100644 spring-5-reactive-netty/README.md create mode 100644 spring-5-reactive-netty/pom.xml create mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java create mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java create mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingController.java create mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingService.java create mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java create mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java create mode 100644 spring-5-reactive-netty/src/main/resources/logback.xml create mode 100644 spring-5-reactive-netty/src/main/resources/sample.jks create mode 100644 spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java create mode 100644 spring-5-reactive-netty/src/test/resources/logback-test.xml diff --git a/pom.xml b/pom.xml index 18e3ace31b..2c173346ee 100644 --- a/pom.xml +++ b/pom.xml @@ -575,6 +575,7 @@ spring-5-reactive-client spring-5-reactive-oauth spring-5-reactive-security + spring-5-reactive-netty spring-5-security spring-5-security-oauth diff --git a/spring-5-reactive-netty/.gitignore b/spring-5-reactive-netty/.gitignore new file mode 100644 index 0000000000..70ed41e73a --- /dev/null +++ b/spring-5-reactive-netty/.gitignore @@ -0,0 +1,11 @@ +# Folders # +**/.idea +**/target + +# Files # +*.log + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-5-reactive-netty/README.md b/spring-5-reactive-netty/README.md new file mode 100644 index 0000000000..09f7cc0e24 --- /dev/null +++ b/spring-5-reactive-netty/README.md @@ -0,0 +1,3 @@ +## Spring 5 Reactive Project With Netty Server + +Includes configuration options for Netty server. diff --git a/spring-5-reactive-netty/pom.xml b/spring-5-reactive-netty/pom.xml new file mode 100644 index 0000000000..48fc0b201f --- /dev/null +++ b/spring-5-reactive-netty/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + com.baeldung + spring-5-reactive-netty + 0.0.1-SNAPSHOT + spring-5-reactive-netty + jar + Spring 5 sample project about reactive web with Netty server + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-webflux + + + + org.projectlombok + lombok + + + + org.springframework.boot + spring-boot-devtools + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java new file mode 100644 index 0000000000..c4ff9c3930 --- /dev/null +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.serverconfig; + +import com.baeldung.serverconfig.client.GreetingWebClient; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ServerConfigApplication { + + public static void main(String[] args) { + SpringApplication.run(ServerConfigApplication.class, args); + + GreetingWebClient webClient = new GreetingWebClient(); + webClient.getResult(); + } +} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java new file mode 100644 index 0000000000..d9bea649c1 --- /dev/null +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java @@ -0,0 +1,37 @@ +package com.baeldung.serverconfig.client; + +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +import lombok.SneakyThrows; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClient; + +public class GreetingWebClient { + + private WebClient client = getWebClient(); + + public void getResult() { + System.out.println("Mono"); + Mono greetingMono = client.get() + .uri("/greet/{name}", "baeldung") + .retrieve() + .bodyToMono(String.class); + + greetingMono.subscribe(System.out::println); + } + + @SneakyThrows + private WebClient getWebClient() { + SslContext sslContext = SslContextBuilder + .forClient() + .trustManager(InsecureTrustManagerFactory.INSTANCE) + .build(); + HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext)); + return WebClient.builder() + .baseUrl("https://localhost:8443") + .clientConnector(new ReactorClientHttpConnector(httpClient)).build(); + } +} \ No newline at end of file diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingController.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingController.java new file mode 100644 index 0000000000..275439a66f --- /dev/null +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingController.java @@ -0,0 +1,23 @@ +package com.baeldung.serverconfig.server; + +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 reactor.core.publisher.Mono; + +@RestController +@RequestMapping("/greet") +public class GreetingController { + + private final GreetingService greetingService; + + public GreetingController(GreetingService greetingService) { + this.greetingService = greetingService; + } + + @GetMapping("/{name}") + private Mono greet(@PathVariable String name) { + return greetingService.greet(name); + } +} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingService.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingService.java new file mode 100644 index 0000000000..5b2b246531 --- /dev/null +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingService.java @@ -0,0 +1,12 @@ +package com.baeldung.serverconfig.server; + +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Service +public class GreetingService { + + public Mono greet(String name) { + return Mono.just("Greeting " + name); + } +} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java new file mode 100644 index 0000000000..be7e442afe --- /dev/null +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java @@ -0,0 +1,31 @@ +package com.baeldung.serverconfig.server; + +import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.stereotype.Component; +import reactor.netty.http.server.HttpServer; + +@Component +public class NettyWebServerFactoryPortCustomizer implements WebServerFactoryCustomizer { + + @Override + public void customize(NettyReactiveWebServerFactory serverFactory) { + serverFactory.addServerCustomizers(new PortCustomizer(8443)); + } + + private static class PortCustomizer implements NettyServerCustomizer { + + private final int port; + + private PortCustomizer(int port) { + this.port = port; + } + + @Override + public HttpServer apply(HttpServer httpServer) { + return httpServer.port(port); + } + } +} + diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java new file mode 100644 index 0000000000..f84e8d143a --- /dev/null +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java @@ -0,0 +1,23 @@ +package com.baeldung.serverconfig.server; + +import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.server.Ssl; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.stereotype.Component; + +@Component +public class NettyWebServerFactorySslCustomizer implements WebServerFactoryCustomizer { + + @Override + public void customize(NettyReactiveWebServerFactory serverFactory) { + Ssl ssl = new Ssl(); + ssl.setEnabled(true); + ssl.setKeyStore("classpath:sample.jks"); + ssl.setKeyAlias("alias"); + ssl.setKeyPassword("password"); + ssl.setKeyStorePassword("secret"); + serverFactory.setSsl(ssl); + serverFactory.setPort(8443); + } +} + diff --git a/spring-5-reactive-netty/src/main/resources/logback.xml b/spring-5-reactive-netty/src/main/resources/logback.xml new file mode 100644 index 0000000000..fc026694b1 --- /dev/null +++ b/spring-5-reactive-netty/src/main/resources/logback.xml @@ -0,0 +1,31 @@ + + + + + + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable + + + + + + netty-access.log + + %msg%n + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-5-reactive-netty/src/main/resources/sample.jks b/spring-5-reactive-netty/src/main/resources/sample.jks new file mode 100644 index 0000000000000000000000000000000000000000..6aa9a28053a591e41453e665e5024e8a8cb78b3d GIT binary patch literal 2264 zcmchYX*3iJ7sqE|hQS!q5Mv)4GM2$i#uAFqC`%7x7baWA*i&dRX>3`uq(XS?3XSYp z%38`&ib7E$8j~$cF^}gt?|I+noW8#w?uYxk=iGD8|K9Vzd#pVc0002(2k@T|2@MMI zqxqr2AhQO*TVi`j@((S;e;g;l$#dAA{>vf0kX$R(Qn4oKgGEYjZ5zti2dw?Z6A zh%LuFCNI?9o+Z1duJL-++e#cjO`zlK?u9s030=k_*wD1#-$FbIDRDnA^vo@fm( zzjt(3VJrGOr0iHXSTM|rYN#>RZ@Dp`PwB2zrDQffLvuoR2~V3ReYa0&vU^dXd8isV zsAf*@!8s%xBvHLseXn6f?1kefe(8uAmAbaF$x{Ykzb6c6jdUwY1$y4tFzsj7 zIghr!T#ODfu@Po!a29@kXQ8kY#(LE<0o7?7PQ|eMeY@Equ?R-6*f@Na3o&stDQ=6( zQzDSQhCnS(9Bu9W_~giknP0vECqUsr4_9y_}nEU`cy z4}dApnAip92wMwgzciAFpc3i}+-#Zlq+iF7d1y}d4Qsp8=%l1N8NIs161I`HmkcpQ zY4*CUCFJJf(2!M{`&qQ}3($KeTQ=)mMrBs`DOb;%Of0tC)9he_p~w&CO#DfCgx(%s z{@|D(brX_Gb}ZDLmGej*JgEl0Et>q~kgTXuJg-PwvRjNx8sBbIShxD=xOySzw{;^X zAvrh5HTg>Xq@<{#^!Kg}B?qz@b<{ebD)yaSf&RChBIJQo-?Ahzw@qopSe^e&>^IuU zydM4Y1_C&>k7u|}=; z63R7$H6zat=hNExxEwXu1fQ*ytuEkP!{w{|#6TIEq1#*ck=6_NM*ILF65tmD-O5&R zMI!-MT<3U~t@}(CN4@RlZ~1I>C=!ywF)dNI{VvH;5Y3(Z4jY^%_c&fsm4Q`<1g|qX z&!h29jXjVE3nJnet*L)XL?-8<>qDbVGP%i^NwOZfwWO7?Mr!X7 zl}sG@9S_5}}td}$xrWIYY=e(VVBiv%A+M-{M z!3_^Tc=pV?niT!{D`!{e@W;MvrZ(OER{x7itVAtwE~spPtPtma|J=5dv&_oE!5H#` zdgXJ;+gJ4hI}*9QX9jpL`Gb)yCe%1}t!&O-^sihyZys%%5uF~WhsR_w(q7;vV5d4P zr%ZUA2}kO+L^2ePTgGT9Ua71w<+)poSyjTdLq&xbUn`<6&SpwFp(HRHUyU6J3WZ_! zfztko79+94Tq%mTYj53(RYcL&1~5`I#+w3`(Q|r+P(aT z%?r(^?IWw~19CB&uvXf(f7&BnEE{zwK4piVU`I4j1j?v5d4N<7VUJ8nM`$7S*mfKR z#9-JzPRZ?{M!@L+0N^V)IyeeP2T|^UK|m0QD+Ibs!wEoml^N!YO#vW~j~jraX(0A3 z6Kux?IRLez`O^X;{!4g%BhcRn>^H*qKZ3*|{_YGuz)KCJcu;)DSES5D2tDE`C02YR0R%Vy1T7k|RQ;3g<0icA$AuP0pOvc~jGl zz+NeKv_FT_;GWK&8XlDUv&hv9kxg?@c!bu?83i=YQ$S!K09Y)Glg3Hz?@|)ZCBlVz zP8i}#XZkMoje3I=h&I!!s_m?Qi@1MR`yv7X*yEs47qOs^t^?&=;*IQ!q&)gq_Sx5* z?fhU8Q*PSe*w7y)FH#P!9R^Xw!lTT+zI39L<&8cViaj$A(Z2Cg7!{V?uuyi#vlNCg z40i}2ivw&y&1-&Nh&WMG`&aIt>)(#tKTJ}^@696Kw1-{IzSOTnFF+0@k$o3%ZHS;Q#;t literal 0 HcmV?d00001 diff --git a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java new file mode 100644 index 0000000000..8bd4e41f1f --- /dev/null +++ b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java @@ -0,0 +1,41 @@ +package com.baeldung.serverconfig.server; + +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; +import reactor.core.publisher.Mono; + +@RunWith(SpringRunner.class) +@WebFluxTest +public class GreetingControllerIntegrationTest { + + @Autowired + private WebTestClient webClient; + + @MockBean + private GreetingService greetingService; + + private final String name = "baeldung"; + + @Before + public void setUp() { + when(greetingService.greet(name)).thenReturn(Mono.just("Hello baeldung")); + } + + @Test + public void shouldGreet() { + webClient.get().uri("/greet/{name}", name) + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo("Hello baeldung"); + } +} \ No newline at end of file diff --git a/spring-5-reactive-netty/src/test/resources/logback-test.xml b/spring-5-reactive-netty/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..39534b2c41 --- /dev/null +++ b/spring-5-reactive-netty/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + + + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable + + + + + + + \ No newline at end of file From 24c5be0e4f2dcfabf60a3ef8accef00eb79f4c6d Mon Sep 17 00:00:00 2001 From: isaolmez Date: Tue, 12 Mar 2019 22:37:51 +0300 Subject: [PATCH 320/496] BAEL-2715: Added code samples for Netty server configuration --- .../com/baeldung/serverconfig/client/GreetingWebClient.java | 2 +- .../server/NettyWebServerFactoryPortCustomizer.java | 1 - .../serverconfig/server/NettyWebServerFactorySslCustomizer.java | 1 - spring-5-reactive-netty/src/main/resources/logback.xml | 2 +- .../serverconfig/server/GreetingControllerIntegrationTest.java | 2 +- spring-5-reactive-netty/src/test/resources/logback-test.xml | 2 +- 6 files changed, 4 insertions(+), 6 deletions(-) diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java index d9bea649c1..77dc98398b 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java @@ -34,4 +34,4 @@ public class GreetingWebClient { .baseUrl("https://localhost:8443") .clientConnector(new ReactorClientHttpConnector(httpClient)).build(); } -} \ No newline at end of file +} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java index be7e442afe..1dda58baa4 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java @@ -28,4 +28,3 @@ public class NettyWebServerFactoryPortCustomizer implements WebServerFactoryCust } } } - diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java index f84e8d143a..0aceae39dc 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java @@ -20,4 +20,3 @@ public class NettyWebServerFactorySslCustomizer implements WebServerFactoryCusto serverFactory.setPort(8443); } } - diff --git a/spring-5-reactive-netty/src/main/resources/logback.xml b/spring-5-reactive-netty/src/main/resources/logback.xml index fc026694b1..48b68c6bf1 100644 --- a/spring-5-reactive-netty/src/main/resources/logback.xml +++ b/spring-5-reactive-netty/src/main/resources/logback.xml @@ -28,4 +28,4 @@ - \ No newline at end of file + diff --git a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java index 8bd4e41f1f..f8e384fb6e 100644 --- a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java +++ b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java @@ -38,4 +38,4 @@ public class GreetingControllerIntegrationTest { .expectBody(String.class) .isEqualTo("Hello baeldung"); } -} \ No newline at end of file +} diff --git a/spring-5-reactive-netty/src/test/resources/logback-test.xml b/spring-5-reactive-netty/src/test/resources/logback-test.xml index 39534b2c41..12cedf5952 100644 --- a/spring-5-reactive-netty/src/test/resources/logback-test.xml +++ b/spring-5-reactive-netty/src/test/resources/logback-test.xml @@ -10,4 +10,4 @@ - \ No newline at end of file + From 57a1096c1fd3e26674367b6b28b1ad8ba2559e38 Mon Sep 17 00:00:00 2001 From: Adam InTae Gerard Date: Tue, 12 Mar 2019 20:55:59 -0700 Subject: [PATCH 321/496] BAEL-2338 (#6150) * BAEL-2338 * Update Application.java * merged and updated * updated pom.xml * improved and updated * corrected per request * removed annotations * formatting --- xml/README.md | 1 + xml/pom.xml | 16 +++ .../com/baeldung/xmlhtml/Application.java | 10 ++ .../java/com/baeldung/xmlhtml/Constants.java | 22 ++++ .../baeldung/xmlhtml/helpers/XMLRunner.java | 16 +++ .../xmlhtml/helpers/jaxb/JAXBHelper.java | 77 ++++++++++++ .../xmlhtml/helpers/jaxp/CustomHandler.java | 34 ++++++ .../xmlhtml/helpers/jaxp/JAXPHelper.java | 90 ++++++++++++++ .../xmlhtml/helpers/stax/STAXHelper.java | 112 ++++++++++++++++++ .../xmlhtml/pojo/jaxb/html/ExampleHTML.java | 38 ++++++ .../xmlhtml/pojo/jaxb/html/elements/Body.java | 29 +++++ .../jaxb/html/elements/CustomElement.java | 18 +++ .../xmlhtml/pojo/jaxb/html/elements/Meta.java | 30 +++++ .../jaxb/html/elements/NestedElement.java | 17 +++ .../xmlhtml/pojo/jaxb/xml/XMLExample.java | 21 ++++ .../pojo/jaxb/xml/elements/Ancestor.java | 28 +++++ .../pojo/jaxb/xml/elements/DescendantOne.java | 19 +++ .../jaxb/xml/elements/DescendantThree.java | 18 +++ .../pojo/jaxb/xml/elements/DescendantTwo.java | 17 +++ .../com/baeldung/xmlhtml/pojo/stax/Body.java | 23 ++++ .../xmlhtml/pojo/stax/CustomElement.java | 13 ++ .../xmlhtml/pojo/stax/NestedElement.java | 13 ++ xml/src/main/resources/xml/in.xml | 11 ++ xml/src/main/resources/xml/jaxb.html | 14 +++ xml/src/main/resources/xml/jaxp.html | 13 ++ xml/src/main/resources/xml/stax.html | 15 +++ 26 files changed, 715 insertions(+) create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/Application.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/Constants.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/helpers/XMLRunner.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxb/JAXBHelper.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxp/CustomHandler.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxp/JAXPHelper.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/helpers/stax/STAXHelper.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/ExampleHTML.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Body.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/CustomElement.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Meta.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/NestedElement.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/XMLExample.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/Ancestor.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantOne.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantThree.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantTwo.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/Body.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/CustomElement.java create mode 100644 xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/NestedElement.java create mode 100644 xml/src/main/resources/xml/in.xml create mode 100644 xml/src/main/resources/xml/jaxb.html create mode 100644 xml/src/main/resources/xml/jaxp.html create mode 100644 xml/src/main/resources/xml/stax.html diff --git a/xml/README.md b/xml/README.md index fb070100db..9d889ef8e9 100644 --- a/xml/README.md +++ b/xml/README.md @@ -4,3 +4,4 @@ - [XML Libraries Support in Java](http://www.baeldung.com/java-xml-libraries) - [DOM parsing with Xerces](http://www.baeldung.com/java-xerces-dom-parsing) - [Write an org.w3.dom.Document to a File](https://www.baeldung.com/java-write-xml-document-file) +- [Convert XML to HTML](https://www.baeldung.com/) diff --git a/xml/pom.xml b/xml/pom.xml index dfdec4da16..ba6a734dc9 100644 --- a/xml/pom.xml +++ b/xml/pom.xml @@ -30,6 +30,22 @@ ${jdom2.version} + + javax.xml + jaxb-api + 2.1 + + + javax.xml + jaxp-api + 1.4.2 + + + javax.xml.stream + stax-api + 1.0-2 + + commons-io diff --git a/xml/src/main/java/com/baeldung/xmlhtml/Application.java b/xml/src/main/java/com/baeldung/xmlhtml/Application.java new file mode 100644 index 0000000000..063a833810 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/Application.java @@ -0,0 +1,10 @@ +package com.baeldung.xmlhtml; + +import com.baeldung.xmlhtml.helpers.XMLRunner; + +public class Application { + + public static void main(String[] args) { + XMLRunner.doWork(); + } +} diff --git a/xml/src/main/java/com/baeldung/xmlhtml/Constants.java b/xml/src/main/java/com/baeldung/xmlhtml/Constants.java new file mode 100644 index 0000000000..88fc5637df --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/Constants.java @@ -0,0 +1,22 @@ +package com.baeldung.xmlhtml; + +public class Constants { + + public static final String XML_FILE_IN = "src/main/resources/xml/in.xml"; + public static final String JAXB_FILE_OUT = "src/main/resources/xml/jaxb.html"; + public static final String JAXP_FILE_OUT = "src/main/resources/xml/jaxp.html"; + public static final String STAX_FILE_OUT = "src/main/resources/xml/stax.html"; + + public static final String EXCEPTION_ENCOUNTERED = "Generic exception! Error: "; + + public static final String LINE_BREAK = System.getProperty("line.separator"); + public static final String WHITE_SPACE = " "; + + public static final String DOCUMENT_START = "Document parsing has begun!"; + public static final String DOCUMENT_END = "Document parsing has ended!"; + public static final String ELEMENT_START = "Element parsing has begun!"; + public static final String ELEMENT_END = "Element parsing has ended!"; + + public static final String BREAK = "\n"; + public static final String TAB = "\t"; +} diff --git a/xml/src/main/java/com/baeldung/xmlhtml/helpers/XMLRunner.java b/xml/src/main/java/com/baeldung/xmlhtml/helpers/XMLRunner.java new file mode 100644 index 0000000000..02b2577795 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/helpers/XMLRunner.java @@ -0,0 +1,16 @@ +package com.baeldung.xmlhtml.helpers; + + +import com.baeldung.xmlhtml.helpers.jaxb.JAXBHelper; +import com.baeldung.xmlhtml.helpers.jaxp.JAXPHelper; +import com.baeldung.xmlhtml.helpers.stax.STAXHelper; + +public class XMLRunner { + + public static void doWork() { + JAXBHelper.example(); + JAXPHelper.saxParser(); + JAXPHelper.documentBuilder(); + STAXHelper.write(STAXHelper.read()); + } +} diff --git a/xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxb/JAXBHelper.java b/xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxb/JAXBHelper.java new file mode 100644 index 0000000000..715f963f2e --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxb/JAXBHelper.java @@ -0,0 +1,77 @@ +package com.baeldung.xmlhtml.helpers.jaxb; + +import com.baeldung.xmlhtml.pojo.jaxb.html.ExampleHTML; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.Body; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.CustomElement; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.Meta; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.NestedElement; +import com.baeldung.xmlhtml.pojo.jaxb.xml.XMLExample; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + +import java.io.File; + +import static com.baeldung.xmlhtml.Constants.*; + +public class JAXBHelper { + + private static void print(String xmlContent) { + System.out.println(xmlContent); + } + + private static Unmarshaller getContextUnmarshaller(Class clazz) { + Unmarshaller unmarshaller = null; + try { + JAXBContext context = JAXBContext.newInstance(clazz); + unmarshaller = context.createUnmarshaller(); + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + return unmarshaller; + } + + private static Marshaller getContextMarshaller(Class clazz) { + Marshaller marshaller = null; + try { + JAXBContext context = JAXBContext.newInstance(clazz); + marshaller = context.createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + marshaller.setProperty("jaxb.fragment", Boolean.TRUE); + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + return marshaller; + } + + public static void example() { + try { + XMLExample xml = (XMLExample) JAXBHelper.getContextUnmarshaller(XMLExample.class).unmarshal(new File(XML_FILE_IN)); + JAXBHelper.print(xml.toString()); + ExampleHTML html = new ExampleHTML(); + + Body body = new Body(); + CustomElement customElement = new CustomElement(); + NestedElement nested = new NestedElement(); + CustomElement child = new CustomElement(); + + customElement.setValue("descendantOne: " + xml.getAncestor().getDescendantOne().getValue()); + child.setValue("descendantThree: " + xml.getAncestor().getDescendantTwo().getDescendantThree().getValue()); + nested.setCustomElement(child); + + body.setCustomElement(customElement); + body.setNestedElement(nested); + + Meta meta = new Meta(); + meta.setTitle("example"); + html.getHead().add(meta); + html.setBody(body); + + JAXBHelper.getContextMarshaller(ExampleHTML.class).marshal(html, new File(JAXB_FILE_OUT)); + + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + } +} \ No newline at end of file diff --git a/xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxp/CustomHandler.java b/xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxp/CustomHandler.java new file mode 100644 index 0000000000..e6351c9e22 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxp/CustomHandler.java @@ -0,0 +1,34 @@ +package com.baeldung.xmlhtml.helpers.jaxp; + +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; + +import static com.baeldung.xmlhtml.Constants.*; + +public class CustomHandler implements ContentHandler { + + public void startDocument() {} + + public void startElement(String uri, String localName, String qName, org.xml.sax.Attributes atts) { } + + public void endDocument() { + System.out.println(DOCUMENT_END); + } + + public void endElement(String uri, String localName, String qName) { } + + public void startPrefixMapping(String prefix, String uri) { } + + public void endPrefixMapping(String prefix) { } + + public void setDocumentLocator(Locator locator) { } + + public void characters(char[] ch, int start, int length) { } + + public void ignorableWhitespace(char[] ch, int start, int length) { } + + public void processingInstruction(String target, String data) { } + + public void skippedEntity(String name) { } + +} diff --git a/xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxp/JAXPHelper.java b/xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxp/JAXPHelper.java new file mode 100644 index 0000000000..3196d543da --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/helpers/jaxp/JAXPHelper.java @@ -0,0 +1,90 @@ +package com.baeldung.xmlhtml.helpers.jaxp; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.XMLReader; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.File; + +import static com.baeldung.xmlhtml.Constants.*; + +public class JAXPHelper { + + private static void print(Document document) { + NodeList list = document.getChildNodes(); + try { + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + String message = + node.getNodeType() + + WHITE_SPACE + + node.getNodeName() + + LINE_BREAK; + System.out.println(message); + } + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + } + + public static void saxParser() { + SAXParserFactory spf = SAXParserFactory.newInstance(); + spf.setNamespaceAware(true); + try { + SAXParser saxParser = spf.newSAXParser(); + XMLReader xmlReader = saxParser.getXMLReader(); + xmlReader.setContentHandler(new CustomHandler()); + xmlReader.parse(XML_FILE_IN); + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + } + + public static void documentBuilder() { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder db = dbf.newDocumentBuilder(); + Document parsed = db.parse(new File(XML_FILE_IN)); + Element xml = parsed.getDocumentElement(); + + Document doc = db.newDocument(); + Element html = doc.createElement("html"); + Element head = doc.createElement("head"); + html.appendChild(head); + + Element body = doc.createElement("body"); + Element descendantOne = doc.createElement("p"); + descendantOne.setTextContent("descendantOne: " + + xml.getElementsByTagName("descendantOne") + .item(0).getTextContent()); + Element descendantThree = doc.createElement("p"); + descendantThree.setTextContent("descendantThree: " + + xml.getElementsByTagName("descendantThree") + .item(0).getTextContent()); + Element nested = doc.createElement("div"); + nested.appendChild(descendantThree); + + body.appendChild(descendantOne); + body.appendChild(nested); + html.appendChild(body); + doc.appendChild(html); + + TransformerFactory tFactory = TransformerFactory.newInstance(); + tFactory + .newTransformer() + .transform(new DOMSource(doc), new StreamResult(new File(JAXP_FILE_OUT))); + + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + } +} diff --git a/xml/src/main/java/com/baeldung/xmlhtml/helpers/stax/STAXHelper.java b/xml/src/main/java/com/baeldung/xmlhtml/helpers/stax/STAXHelper.java new file mode 100644 index 0000000000..a9b9217b6a --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/helpers/stax/STAXHelper.java @@ -0,0 +1,112 @@ +package com.baeldung.xmlhtml.helpers.stax; + +import com.baeldung.xmlhtml.pojo.stax.Body; +import com.baeldung.xmlhtml.pojo.stax.CustomElement; +import com.baeldung.xmlhtml.pojo.stax.NestedElement; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import java.io.FileInputStream; +import java.io.FileWriter; + +import static com.baeldung.xmlhtml.Constants.*; + +public class STAXHelper { + + private static XMLStreamReader reader() { + XMLStreamReader xmlStreamReader = null; + try { + xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(new FileInputStream(XML_FILE_IN)); + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + return xmlStreamReader; + } + + private static XMLStreamWriter writer() { + XMLStreamWriter xmlStreamWriter = null; + try { + xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(new FileWriter(STAX_FILE_OUT)); + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + return xmlStreamWriter; + } + + public static Body read() { + Body body = new Body(); + try { + XMLStreamReader xmlStreamReader = reader(); + + CustomElement customElement = new CustomElement(); + NestedElement nestedElement = new NestedElement(); + CustomElement child = new CustomElement(); + + while (xmlStreamReader.hasNext()) { + xmlStreamReader.next(); + if (xmlStreamReader.isStartElement()) { + System.out.println(xmlStreamReader.getLocalName()); + if (xmlStreamReader.getLocalName().equals("descendantOne")) { + customElement.setValue(xmlStreamReader.getElementText()); + } + if (xmlStreamReader.getLocalName().equals("descendantThree")) { + child.setValue(xmlStreamReader.getElementText()); + } + } + } + + nestedElement.setCustomElement(child); + body.setCustomElement(customElement); + body.setNestedElement(nestedElement); + + xmlStreamReader.close(); + + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + return body; + } + + public static void write(Body body) { + try { + + XMLStreamWriter xmlStreamWriter = writer(); + xmlStreamWriter.writeStartElement("html"); + xmlStreamWriter.writeCharacters(BREAK + TAB); + xmlStreamWriter.writeStartElement("head"); + xmlStreamWriter.writeCharacters(BREAK + TAB + TAB); + xmlStreamWriter.writeStartElement("meta"); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeCharacters(BREAK + TAB); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeCharacters(BREAK + TAB); + xmlStreamWriter.writeStartElement("body"); + xmlStreamWriter.writeCharacters(BREAK + TAB + TAB); + xmlStreamWriter.writeStartElement("p"); + xmlStreamWriter.writeCharacters("descendantOne: " + body.getCustomElement().getValue()); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeCharacters(BREAK + TAB + TAB); + xmlStreamWriter.writeStartElement("div"); + xmlStreamWriter.writeCharacters(BREAK + TAB + TAB + TAB); + xmlStreamWriter.writeStartElement("p"); + xmlStreamWriter.writeCharacters(BREAK); + xmlStreamWriter.writeCharacters(TAB + TAB + TAB + TAB + "descendantThree: " + body.getNestedElement().getCustomElement().getValue()); + xmlStreamWriter.writeCharacters(BREAK + TAB + TAB + TAB); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeCharacters(BREAK + TAB + TAB); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeCharacters(BREAK + TAB); + xmlStreamWriter.writeEndElement(); + xmlStreamWriter.writeCharacters(BREAK); + xmlStreamWriter.writeEndDocument(); + xmlStreamWriter.flush(); + xmlStreamWriter.close(); + + } catch (Exception ex) { + System.out.println(EXCEPTION_ENCOUNTERED + ex); + } + + } +} diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/ExampleHTML.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/ExampleHTML.java new file mode 100644 index 0000000000..d44c81f309 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/ExampleHTML.java @@ -0,0 +1,38 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html; + +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.Body; +import com.baeldung.xmlhtml.pojo.jaxb.html.elements.Meta; + +import javax.xml.bind.annotation.*; +import java.util.ArrayList; +import java.util.List; + +@XmlType(propOrder = {"head", "body"}) +@XmlRootElement(name = "html") +public class ExampleHTML { + + private List head = new ArrayList<>(); + + private Body body; + + public ExampleHTML() { } + + public List getHead() { + return head; + } + + @XmlElementWrapper(name = "head") + @XmlElement(name = "meta") + public void setHead(List head) { + this.head = head; + } + + public Body getBody() { + return body; + } + + @XmlElement(name = "body") + public void setBody(Body body) { + this.body = body; + } +} diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Body.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Body.java new file mode 100644 index 0000000000..36c6c13a04 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Body.java @@ -0,0 +1,29 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html.elements; + +import javax.xml.bind.annotation.XmlElement; + +public class Body { + + private CustomElement customElement; + + public CustomElement getCustomElement() { + return customElement; + } + + @XmlElement(name = "p") + public void setCustomElement(CustomElement customElement) { + this.customElement = customElement; + } + + private NestedElement nestedElement; + + public NestedElement getNestedElement() { + return nestedElement; + } + + @XmlElement(name = "div") + public void setNestedElement(NestedElement nestedElement) { + this.nestedElement = nestedElement; + } + +} \ No newline at end of file diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/CustomElement.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/CustomElement.java new file mode 100644 index 0000000000..832c5e746e --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/CustomElement.java @@ -0,0 +1,18 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html.elements; + +import javax.xml.bind.annotation.XmlValue; + +public class CustomElement { + + private String value; + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Meta.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Meta.java new file mode 100644 index 0000000000..11b6b86c05 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/Meta.java @@ -0,0 +1,30 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html.elements; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlValue; + +public class Meta { + + private String title; + + public String getTitle() { + return title; + } + + @XmlAttribute(name = "title") + public void setTitle(String title) { + this.title = title; + } + + private String value; + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} \ No newline at end of file diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/NestedElement.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/NestedElement.java new file mode 100644 index 0000000000..20557064bb --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/html/elements/NestedElement.java @@ -0,0 +1,17 @@ +package com.baeldung.xmlhtml.pojo.jaxb.html.elements; + +import javax.xml.bind.annotation.XmlElement; + +public class NestedElement { + + private CustomElement customElement; + + public CustomElement getCustomElement() { + return customElement; + } + + @XmlElement(name = "p") + public void setCustomElement(CustomElement customElement) { + this.customElement = customElement; + } +} \ No newline at end of file diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/XMLExample.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/XMLExample.java new file mode 100644 index 0000000000..587cf69223 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/XMLExample.java @@ -0,0 +1,21 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml; + +import com.baeldung.xmlhtml.pojo.jaxb.xml.elements.Ancestor; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "xmlexample") +public class XMLExample { + + private Ancestor ancestor; + + @XmlElement(name = "ancestor") + public void setAncestor(Ancestor ancestor) { + this.ancestor = ancestor; + } + + public Ancestor getAncestor() { + return ancestor; + } +} \ No newline at end of file diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/Ancestor.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/Ancestor.java new file mode 100644 index 0000000000..ff2b928206 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/Ancestor.java @@ -0,0 +1,28 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml.elements; + +import javax.xml.bind.annotation.XmlElement; + +public class Ancestor { + + private DescendantOne descendantOne; + private DescendantTwo descendantTwo; + + public DescendantOne getDescendantOne() { + return descendantOne; + } + + @XmlElement(name = "descendantOne") + public void setDescendantOne(DescendantOne descendantOne) { + this.descendantOne = descendantOne; + } + + public DescendantTwo getDescendantTwo() { + return descendantTwo; + } + + @XmlElement(name = "descendantTwo") + public void setDescendantTwo(DescendantTwo descendantTwo) { + this.descendantTwo = descendantTwo; + } +} + diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantOne.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantOne.java new file mode 100644 index 0000000000..50624cb9fa --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantOne.java @@ -0,0 +1,19 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml.elements; + +import javax.xml.bind.annotation.XmlValue; + +public class DescendantOne { + + private String value; + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} + diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantThree.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantThree.java new file mode 100644 index 0000000000..7c3ce9b6f7 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantThree.java @@ -0,0 +1,18 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml.elements; + +import javax.xml.bind.annotation.XmlValue; + +public class DescendantThree { + + private String value; + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} \ No newline at end of file diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantTwo.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantTwo.java new file mode 100644 index 0000000000..1ca989560b --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/jaxb/xml/elements/DescendantTwo.java @@ -0,0 +1,17 @@ +package com.baeldung.xmlhtml.pojo.jaxb.xml.elements; + +import javax.xml.bind.annotation.XmlElement; + +public class DescendantTwo { + + private DescendantThree descendantThree; + + public DescendantThree getDescendantThree() { + return descendantThree; + } + + @XmlElement(name = "descendantThree") + public void setDescendant(DescendantThree descendantThree) { + this.descendantThree = descendantThree; + } +} \ No newline at end of file diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/Body.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/Body.java new file mode 100644 index 0000000000..630dfe967f --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/Body.java @@ -0,0 +1,23 @@ +package com.baeldung.xmlhtml.pojo.stax; + +public class Body { + + private CustomElement customElement; + + public CustomElement getCustomElement() { + return customElement; + } + public void setCustomElement(CustomElement customElement) { + this.customElement = customElement; + } + + private NestedElement nestedElement; + + public NestedElement getNestedElement() { + return nestedElement; + } + public void setNestedElement(NestedElement nestedElement) { + this.nestedElement = nestedElement; + } + +} \ No newline at end of file diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/CustomElement.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/CustomElement.java new file mode 100644 index 0000000000..6fc1d7b787 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/CustomElement.java @@ -0,0 +1,13 @@ +package com.baeldung.xmlhtml.pojo.stax; + +public class CustomElement { + + private String value; + + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } +} diff --git a/xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/NestedElement.java b/xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/NestedElement.java new file mode 100644 index 0000000000..146ee068af --- /dev/null +++ b/xml/src/main/java/com/baeldung/xmlhtml/pojo/stax/NestedElement.java @@ -0,0 +1,13 @@ +package com.baeldung.xmlhtml.pojo.stax; + +public class NestedElement { + + private CustomElement customElement; + + public CustomElement getCustomElement() { + return customElement; + } + public void setCustomElement(CustomElement customElement) { + this.customElement = customElement; + } +} diff --git a/xml/src/main/resources/xml/in.xml b/xml/src/main/resources/xml/in.xml new file mode 100644 index 0000000000..6fcb404012 --- /dev/null +++ b/xml/src/main/resources/xml/in.xml @@ -0,0 +1,11 @@ + + + + Yo + + + DustyOrb + + + + \ No newline at end of file diff --git a/xml/src/main/resources/xml/jaxb.html b/xml/src/main/resources/xml/jaxb.html new file mode 100644 index 0000000000..80b894cff7 --- /dev/null +++ b/xml/src/main/resources/xml/jaxb.html @@ -0,0 +1,14 @@ + + + + + + +

descendantOne: Yo

+
+

descendantThree: + DustyOrb +

+
+ + diff --git a/xml/src/main/resources/xml/jaxp.html b/xml/src/main/resources/xml/jaxp.html new file mode 100644 index 0000000000..5392eef509 --- /dev/null +++ b/xml/src/main/resources/xml/jaxp.html @@ -0,0 +1,13 @@ + + + + + +

descendantOne: Yo

+
+

descendantThree: + DustyOrb +

+
+ + diff --git a/xml/src/main/resources/xml/stax.html b/xml/src/main/resources/xml/stax.html new file mode 100644 index 0000000000..01951dc7de --- /dev/null +++ b/xml/src/main/resources/xml/stax.html @@ -0,0 +1,15 @@ + + + + + +

descendantOne: Yo

+
+

+ descendantThree: + DustyOrb + +

+
+ + \ No newline at end of file From 8ecfd8de08ea13acfd0559116359f10c080d7f4a Mon Sep 17 00:00:00 2001 From: pcoates33 Date: Wed, 13 Mar 2019 04:54:34 +0000 Subject: [PATCH 322/496] Bael 2721 - JSON deserialization mapping different JSON fields to same Java field (#6434) * BAEL-2721 Examples of @JsonAlias and Gson's alternate parameter * BAEL-2721 Update class and method names for JsonAlias and GsonAlternate --- .../org/baeldung/gson/entities/Weather.java | 40 +++++++++++++++++ .../GsonAlternateUnitTest.java | 39 ++++++++++++++++ .../baeldung/jackson/entities/Weather.java | 44 +++++++++++++++++++ .../jsonalias/JsonAliasUnitTest.java | 38 ++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 gson/src/main/java/org/baeldung/gson/entities/Weather.java create mode 100644 gson/src/test/java/org/baeldung/gson/deserialization/GsonAlternateUnitTest.java create mode 100644 jackson/src/main/java/com/baeldung/jackson/entities/Weather.java create mode 100644 jackson/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java diff --git a/gson/src/main/java/org/baeldung/gson/entities/Weather.java b/gson/src/main/java/org/baeldung/gson/entities/Weather.java new file mode 100644 index 0000000000..383e9ef41c --- /dev/null +++ b/gson/src/main/java/org/baeldung/gson/entities/Weather.java @@ -0,0 +1,40 @@ +package org.baeldung.gson.entities; + +import com.google.gson.annotations.SerializedName; + +public class Weather { + + @SerializedName(value = "location", alternate = "place") + private String location; + + @SerializedName(value = "temp", alternate = "temperature") + private int temp; + + @SerializedName(value = "outlook", alternate = "weather") + private String outlook; + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public int getTemp() { + return temp; + } + + public void setTemp(int temp) { + this.temp = temp; + } + + public String getOutlook() { + return outlook; + } + + public void setOutlook(String outlook) { + this.outlook = outlook; + } + +} diff --git a/gson/src/test/java/org/baeldung/gson/deserialization/GsonAlternateUnitTest.java b/gson/src/test/java/org/baeldung/gson/deserialization/GsonAlternateUnitTest.java new file mode 100644 index 0000000000..f3a5d24e3e --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/deserialization/GsonAlternateUnitTest.java @@ -0,0 +1,39 @@ +package org.baeldung.gson.deserialization; + +import static org.junit.Assert.assertEquals; + +import org.baeldung.gson.entities.Weather; +import org.junit.Test; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class GsonAlternateUnitTest { + + @Test + public void givenTwoJsonFormats_whenDeserialized_thenWeatherObjectsCreated() throws Exception { + + Gson gson = new GsonBuilder().create(); + + Weather weather = gson.fromJson("{" + + "\"location\": \"London\"," + + "\"temp\": 15," + + "\"weather\": \"Cloudy\"" + + "}", Weather.class); + + assertEquals("London", weather.getLocation()); + assertEquals("Cloudy", weather.getOutlook()); + assertEquals(15, weather.getTemp()); + + weather = gson.fromJson("{" + + "\"place\": \"Lisbon\"," + + "\"temperature\": 35," + + "\"outlook\": \"Sunny\"" + + "}", Weather.class); + + assertEquals("Lisbon", weather.getLocation()); + assertEquals("Sunny", weather.getOutlook()); + assertEquals(35, weather.getTemp()); + + } +} diff --git a/jackson/src/main/java/com/baeldung/jackson/entities/Weather.java b/jackson/src/main/java/com/baeldung/jackson/entities/Weather.java new file mode 100644 index 0000000000..4a8cea052f --- /dev/null +++ b/jackson/src/main/java/com/baeldung/jackson/entities/Weather.java @@ -0,0 +1,44 @@ +package com.baeldung.jackson.entities; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Weather { + + @JsonProperty("location") + @JsonAlias("place") + private String location; + + @JsonProperty("temp") + @JsonAlias("temperature") + private int temp; + + @JsonProperty("outlook") + @JsonAlias("weather") + private String outlook; + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public int getTemp() { + return temp; + } + + public void setTemp(int temp) { + this.temp = temp; + } + + public String getOutlook() { + return outlook; + } + + public void setOutlook(String outlook) { + this.outlook = outlook; + } + +} diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java new file mode 100644 index 0000000000..b5940a7bd7 --- /dev/null +++ b/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.jackson.deserialization.jsonalias; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.jackson.entities.Weather; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonAliasUnitTest { + + @Test + public void givenTwoJsonFormats_whenDeserialized_thenWeatherObjectsCreated() throws Exception { + + ObjectMapper mapper = new ObjectMapper(); + + Weather weather = mapper.readValue("{" + + "\"location\": \"London\"," + + "\"temp\": 15," + + "\"weather\": \"Cloudy\"" + + "}", Weather.class); + + assertEquals("London", weather.getLocation()); + assertEquals("Cloudy", weather.getOutlook()); + assertEquals(15, weather.getTemp()); + + weather = mapper.readValue("{" + + "\"place\": \"Lisbon\"," + + "\"temperature\": 35," + + "\"outlook\": \"Sunny\"" + + "}", Weather.class); + + assertEquals("Lisbon", weather.getLocation()); + assertEquals("Sunny", weather.getOutlook()); + assertEquals(35, weather.getTemp()); + + } +} From c9ac3be4c5b7e04fef8cc79ab2e7bbddccbe4b0c Mon Sep 17 00:00:00 2001 From: letcodespeak <44544000+letcodespeak@users.noreply.github.com> Date: Wed, 13 Mar 2019 15:58:13 +1100 Subject: [PATCH 323/496] BAEL-2569 : EnvironmentPostProcessor in Spring Boot (#6479) * BAEL-2569 : EnvironmentPostProcessor in Spring Boot * BAEL-2569 add test * BAEL-2569 update test --- .../PriceCalculationApplication.java | 59 +++++++++++++++ ...ceCalculationEnvironmentPostProcessor.java | 71 +++++++++++++++++++ .../PriceCalculationAutoConfig.java | 32 +++++++++ .../calculator/GrossPriceCalculator.java | 23 ++++++ .../calculator/NetPriceCalculator.java | 17 +++++ .../calculator/PriceCalculator.java | 5 ++ .../service/PriceCalculationService.java | 17 +++++ .../main/resources/META-INF/spring.factories | 8 ++- ...ationEnvironmentPostProcessorLiveTest.java | 26 +++++++ 9 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java create mode 100644 spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java create mode 100644 spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java new file mode 100644 index 0000000000..01be08d6ae --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationApplication.java @@ -0,0 +1,59 @@ +package com.baeldung.environmentpostprocessor; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import com.baeldung.environmentpostprocessor.service.PriceCalculationService; + +@SpringBootApplication +public class PriceCalculationApplication implements CommandLineRunner { + + @Autowired + PriceCalculationService priceCalculationService; + + private static final Logger logger = LoggerFactory.getLogger(PriceCalculationApplication.class); + + public static void main(String[] args) { + SpringApplication.run(PriceCalculationApplication.class, args); + } + + @Override + public void run(String... args) throws Exception { + + List params = Arrays.stream(args) + .collect(Collectors.toList()); + if (verifyArguments(params)) { + double singlePrice = Double.valueOf(params.get(0)); + int quantity = Integer.valueOf(params.get(1)); + priceCalculationService.productTotalPrice(singlePrice, quantity); + } else { + logger.error("Invalid arguments " + params.toString()); + } + + } + + private boolean verifyArguments(List args) { + boolean successful = true; + if (args.size() != 2) { + successful = false; + return successful; + } + try { + double singlePrice = Double.valueOf(args.get(0)); + int quantity = Integer.valueOf(args.get(1)); + } catch (NumberFormatException e) { + successful = false; + } + return successful; + + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java new file mode 100644 index 0000000000..1b3099453e --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java @@ -0,0 +1,71 @@ +package com.baeldung.environmentpostprocessor; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; +import org.springframework.core.env.StandardEnvironment; + +public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { + + private static final Logger logger = LoggerFactory.getLogger(PriceCalculationEnvironmentPostProcessor.class); + + public static final int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE; + private int order = DEFAULT_ORDER; + private static final String PROPERTY_PREFIX = "com.baeldung.environmentpostprocessor."; + private static final String OS_ENV_PROPERTY_CALCUATION_MODE = "calculation_mode"; + private static final String OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE = "gross_calculation_tax_rate"; + private static final String OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE = "NET"; + private static final double OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE = 0; + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + + PropertySource systemEnvironmentPropertySource = environment.getPropertySources() + .get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); + + Map priceCalculationConfiguration = new LinkedHashMap<>(); + if (isActive(systemEnvironmentPropertySource)) { + priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), systemEnvironmentPropertySource.getProperty(OS_ENV_PROPERTY_CALCUATION_MODE)); + priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), systemEnvironmentPropertySource.getProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)); + } else { + logger.warn("System environment variables [calculation_mode,gross_calculation_tax_rate] not detected, fallback to default value [calcuation_mode={},gross_calcuation_tax_rate={}]", OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE, + OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE); + priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + } + + PropertySource priceCalcuationPropertySource = new MapPropertySource("priceCalcuationPS", priceCalculationConfiguration); + environment.getPropertySources() + .addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, priceCalcuationPropertySource); + + } + + private String key(String key) { + return PROPERTY_PREFIX + key.replaceAll("\\_", "."); + } + + private boolean isActive(PropertySource systemEnvpropertySource) { + if (systemEnvpropertySource.containsProperty(OS_ENV_PROPERTY_CALCUATION_MODE) && systemEnvpropertySource.containsProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)) { + return true; + } else + return false; + } + + public void setOrder(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return order; + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java new file mode 100644 index 0000000000..c884f043a0 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/autoconfig/PriceCalculationAutoConfig.java @@ -0,0 +1,32 @@ +package com.baeldung.environmentpostprocessor.autoconfig; + +import org.springframework.boot.autoconfigure.AutoConfigureOrder; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; + +import com.baeldung.environmentpostprocessor.calculator.GrossPriceCalculator; +import com.baeldung.environmentpostprocessor.calculator.NetPriceCalculator; +import com.baeldung.environmentpostprocessor.calculator.PriceCalculator; + +@Configuration +@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) +public class PriceCalculationAutoConfig { + + @Bean + @ConditionalOnProperty(name = "com.baeldung.environmentpostprocessor.calculation.mode", havingValue = "NET") + @ConditionalOnMissingBean + public PriceCalculator getNetPriceCalculator() { + return new NetPriceCalculator(); + } + + @Bean + @ConditionalOnProperty(name = "com.baeldung.environmentpostprocessor.calculation.mode", havingValue = "GROSS") + @ConditionalOnMissingBean + public PriceCalculator getGrossPriceCalculator() { + return new GrossPriceCalculator(); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java new file mode 100644 index 0000000000..f8f797bd66 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/GrossPriceCalculator.java @@ -0,0 +1,23 @@ +package com.baeldung.environmentpostprocessor.calculator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; + +public class GrossPriceCalculator implements PriceCalculator { + + private static final Logger logger = LoggerFactory.getLogger(GrossPriceCalculator.class); + + @Value("${com.baeldung.environmentpostprocessor.gross.calculation.tax.rate}") + double taxRate; + + @Override + public double calculate(double singlePrice, int quantity) { + logger.info("Gross based price calculation with input parameters [singlePrice = {},quantity= {} ], {} percent tax applied.", singlePrice, quantity, taxRate * 100); + double netPrice = singlePrice * quantity; + double result = Math.round(netPrice * (1 + taxRate)); + logger.info("Calcuation result is {}", result); + return result; + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java new file mode 100644 index 0000000000..263dff6247 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/NetPriceCalculator.java @@ -0,0 +1,17 @@ +package com.baeldung.environmentpostprocessor.calculator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NetPriceCalculator implements PriceCalculator { + + private static final Logger logger = LoggerFactory.getLogger(GrossPriceCalculator.class); + + @Override + public double calculate(double singlePrice, int quantity) { + logger.info("Net based price calculation with input parameters [singlePrice = {},quantity= {} ], NO tax applied.", singlePrice, quantity); + double result = Math.round(singlePrice * quantity); + logger.info("Calcuation result is {}", result); + return result; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java new file mode 100644 index 0000000000..9d7bef93a4 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/calculator/PriceCalculator.java @@ -0,0 +1,5 @@ +package com.baeldung.environmentpostprocessor.calculator; + +public interface PriceCalculator { + public double calculate(double singlePrice, int quantity); +} diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java new file mode 100644 index 0000000000..0e4eb39506 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/service/PriceCalculationService.java @@ -0,0 +1,17 @@ +package com.baeldung.environmentpostprocessor.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baeldung.environmentpostprocessor.calculator.PriceCalculator; + +@Service +public class PriceCalculationService { + + @Autowired + PriceCalculator priceCalculator; + + public double productTotalPrice(double singlePrice, int quantity) { + return priceCalculator.calculate(singlePrice, quantity); + } +} diff --git a/spring-boot/src/main/resources/META-INF/spring.factories b/spring-boot/src/main/resources/META-INF/spring.factories index e3d3aa4c8e..d8a01bbf82 100644 --- a/spring-boot/src/main/resources/META-INF/spring.factories +++ b/spring-boot/src/main/resources/META-INF/spring.factories @@ -1 +1,7 @@ -org.springframework.boot.diagnostics.FailureAnalyzer=com.baeldung.failureanalyzer.MyBeanNotOfRequiredTypeFailureAnalyzer \ No newline at end of file +org.springframework.boot.diagnostics.FailureAnalyzer=com.baeldung.failureanalyzer.MyBeanNotOfRequiredTypeFailureAnalyzer +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.baeldung.environmentpostprocessor.autoconfig.PriceCalculationAutoConfig + +org.springframework.boot.env.EnvironmentPostProcessor=\ +com.baeldung.environmentpostprocessor.PriceCalculationEnvironmentPostProcessor + diff --git a/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java b/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java new file mode 100644 index 0000000000..54af217346 --- /dev/null +++ b/spring-boot/src/test/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessorLiveTest.java @@ -0,0 +1,26 @@ +package com.baeldung.environmentpostprocessor; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.environmentpostprocessor.service.PriceCalculationService; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = PriceCalculationApplication.class) +public class PriceCalculationEnvironmentPostProcessorLiveTest { + + @Autowired + PriceCalculationService pcService; + + @Test + public void whenSetNetEnvironmentVariablebyDefault_thenNoTaxApplied() { + double total = pcService.productTotalPrice(100, 4); + assertEquals(400.0, total, 0); + } + +} From 9578f0de93099ad5c8de8a0140cb7eaeab978b21 Mon Sep 17 00:00:00 2001 From: Jan Hauer Date: Mon, 11 Mar 2019 07:33:59 +0100 Subject: [PATCH 324/496] BAEL-2400: Adds examples for currying --- patterns/design-patterns/README.md | 1 + .../java/com/baeldung/currying/Letter.java | 110 ++++++++++++++++++ .../com/baeldung/currying/LetterUnitTest.java | 58 +++++++++ 3 files changed, 169 insertions(+) create mode 100644 patterns/design-patterns/src/main/java/com/baeldung/currying/Letter.java create mode 100644 patterns/design-patterns/src/test/java/com/baeldung/currying/LetterUnitTest.java diff --git a/patterns/design-patterns/README.md b/patterns/design-patterns/README.md index a4513b7d95..c43ea48505 100644 --- a/patterns/design-patterns/README.md +++ b/patterns/design-patterns/README.md @@ -19,3 +19,4 @@ - [The Command Pattern in Java](http://www.baeldung.com/java-command-pattern) - [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods) - [The Adapter Pattern in Java](https://www.baeldung.com/java-adapter-pattern) +- [Currying in Java](https://baeldung.com/currying-in-java) diff --git a/patterns/design-patterns/src/main/java/com/baeldung/currying/Letter.java b/patterns/design-patterns/src/main/java/com/baeldung/currying/Letter.java new file mode 100644 index 0000000000..0939569d3c --- /dev/null +++ b/patterns/design-patterns/src/main/java/com/baeldung/currying/Letter.java @@ -0,0 +1,110 @@ +package com.baeldung.currying; + +import java.time.LocalDate; +import java.util.Objects; +import java.util.function.BiFunction; +import java.util.function.Function; + +public class Letter { + private String returningAddress; + private String insideAddress; + private LocalDate dateOfLetter; + private String salutation; + private String body; + private String closing; + + Letter(String returningAddress, String insideAddress, LocalDate dateOfLetter, String salutation, String body, String closing) { + this.returningAddress = returningAddress; + this.insideAddress = insideAddress; + this.dateOfLetter = dateOfLetter; + this.salutation = salutation; + this.body = body; + this.closing = closing; + } + + Letter(String salutation, String body) { + this(null, null, LocalDate.now(), salutation, body, null); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Letter letter = (Letter) o; + return Objects.equals(returningAddress, letter.returningAddress) && + Objects.equals(insideAddress, letter.insideAddress) && + Objects.equals(dateOfLetter, letter.dateOfLetter) && + Objects.equals(salutation, letter.salutation) && + Objects.equals(body, letter.body) && + Objects.equals(closing, letter.closing); + } + + @Override + public int hashCode() { + return Objects.hash(returningAddress, insideAddress, dateOfLetter, salutation, body, closing); + } + + @Override + public String toString() { + return "Letter{" + "returningAddress='" + returningAddress + '\'' + ", insideAddress='" + insideAddress + '\'' + + ", dateOfLetter=" + dateOfLetter + ", salutation='" + salutation + '\'' + ", body='" + body + '\'' + + ", closing='" + closing + '\'' + '}'; + } + + static Letter createLetter(String salutation, String body) { + return new Letter(salutation, body); + } + + static BiFunction SIMPLE_LETTER_CREATOR = // + (salutation, body) -> new Letter(salutation, body); + + static Function> SIMPLE_CURRIED_LETTER_CREATOR = // + saluation -> body -> new Letter(saluation, body); + + static Function>>>>> LETTER_CREATOR = // + returnAddress + -> closing + -> dateOfLetter + -> insideAddress + -> salutation + -> body + -> new Letter(returnAddress, insideAddress, dateOfLetter, salutation, body, closing); + + static AddReturnAddress builder() { + return returnAddress + -> closing + -> dateOfLetter + -> insideAddress + -> salutation + -> body + -> new Letter(returnAddress, insideAddress, dateOfLetter, salutation, body, closing); + } + + interface AddReturnAddress { + Letter.AddClosing withReturnAddress(String returnAddress); + } + + interface AddClosing { + Letter.AddDateOfLetter withClosing(String closing); + } + + interface AddDateOfLetter { + Letter.AddInsideAddress withDateOfLetter(LocalDate dateOfLetter); + } + + interface AddInsideAddress { + Letter.AddSalutation withInsideAddress(String insideAddress); + } + + interface AddSalutation { + Letter.AddBody withSalutation(String salutation); + } + + interface AddBody { + Letter withBody(String body); + } +} \ No newline at end of file diff --git a/patterns/design-patterns/src/test/java/com/baeldung/currying/LetterUnitTest.java b/patterns/design-patterns/src/test/java/com/baeldung/currying/LetterUnitTest.java new file mode 100644 index 0000000000..bf1bafe72c --- /dev/null +++ b/patterns/design-patterns/src/test/java/com/baeldung/currying/LetterUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.currying; + +import org.junit.Test; + +import java.time.LocalDate; + +import static com.baeldung.currying.Letter.LETTER_CREATOR; +import static com.baeldung.currying.Letter.SIMPLE_CURRIED_LETTER_CREATOR; +import static com.baeldung.currying.Letter.SIMPLE_LETTER_CREATOR; +import static org.junit.Assert.assertEquals; + +public class LetterUnitTest { + private static final String BODY = "BODY"; + private static final String SALUTATION = "SALUTATION"; + private static final String RETURNING_ADDRESS = "RETURNING ADDRESS"; + private static final String INSIDE_ADDRESS = "INSIDE ADDRESS"; + private static final LocalDate DATE_OF_LETTER = LocalDate.of(2013, 3, 1); + private static final String CLOSING = "CLOSING"; + private static final Letter SIMPLE_LETTER = new Letter(SALUTATION, BODY); + private static final Letter LETTER = new Letter(RETURNING_ADDRESS, INSIDE_ADDRESS, DATE_OF_LETTER, SALUTATION, BODY, CLOSING); + + @Test + public void whenStaticCreateMethodIsCalled_thenaSimpleLetterIsCreated() { + assertEquals(SIMPLE_LETTER, Letter.createLetter(SALUTATION, BODY)); + } + + @Test + public void whenStaticBiFunctionIsCalled_thenaSimpleLetterIsCreated() { + assertEquals(SIMPLE_LETTER, SIMPLE_LETTER_CREATOR.apply(SALUTATION, BODY)); + } + + @Test + public void whenStaticSimpleCurriedFunctionIsCalled_thenaSimpleLetterIsCreated() { + assertEquals(SIMPLE_LETTER, SIMPLE_CURRIED_LETTER_CREATOR.apply(SALUTATION).apply(BODY)); + } + + @Test + public void whenStaticCurriedFunctionIsCalled_thenaLetterIsCreated() { + assertEquals(LETTER, LETTER_CREATOR + .apply(RETURNING_ADDRESS) + .apply(CLOSING) + .apply(DATE_OF_LETTER) + .apply(INSIDE_ADDRESS) + .apply(SALUTATION) + .apply(BODY)); + } + + @Test + public void whenStaticBuilderIsCalled_thenaLetterIsCreated() { + assertEquals(LETTER, Letter.builder() + .withReturnAddress(RETURNING_ADDRESS) + .withClosing(CLOSING) + .withDateOfLetter(DATE_OF_LETTER) + .withInsideAddress(INSIDE_ADDRESS) + .withSalutation(SALUTATION) + .withBody(BODY)); + } +} \ No newline at end of file From 327f00f4d97fff317dbdd566c15b861bde19147f Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Wed, 13 Mar 2019 15:17:18 +0400 Subject: [PATCH 325/496] move primitive maps code to java-collections-maps-2 --- java-collections-maps-2/pom.xml | 45 +++++++++++++++++++ .../java/com/baeldung/map}/PrimitiveMaps.java | 14 ++++-- libraries/pom.xml | 15 ------- 3 files changed, 55 insertions(+), 19 deletions(-) create mode 100644 java-collections-maps-2/pom.xml rename {libraries/src/main/java/com/baeldung/primitives => java-collections-maps-2/src/main/java/com/baeldung/map}/PrimitiveMaps.java (73%) diff --git a/java-collections-maps-2/pom.xml b/java-collections-maps-2/pom.xml new file mode 100644 index 0000000000..b025c5e32d --- /dev/null +++ b/java-collections-maps-2/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + java-collections-maps-2 + 0.1.0-SNAPSHOT + java-collections-maps-2 + jar + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + org.eclipse.collections + eclipse-collections + ${eclipse-collections.version} + + + net.sf.trove4j + trove4j + 3.0.2 + + + it.unimi.dsi + fastutil + 8.1.0 + + + colt + colt + 1.2.0 + + + + + 8.2.0 + + + \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java b/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java similarity index 73% rename from libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java rename to java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java index 89e99acfc7..c13aa19424 100644 --- a/libraries/src/main/java/com/baeldung/primitives/PrimitiveMaps.java +++ b/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java @@ -1,12 +1,18 @@ -package com.baeldung.primitives; +package com.baeldung.map; import cern.colt.map.AbstractIntDoubleMap; import cern.colt.map.OpenIntDoubleHashMap; import gnu.trove.map.TDoubleIntMap; import gnu.trove.map.hash.TDoubleIntHashMap; -import it.unimi.dsi.fastutil.ints.*; -import org.eclipse.collections.api.map.primitive.*; -import org.eclipse.collections.impl.factory.primitive.*; +import it.unimi.dsi.fastutil.ints.Int2BooleanMap; +import it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2BooleanSortedMap; +import it.unimi.dsi.fastutil.ints.Int2BooleanSortedMaps; +import org.eclipse.collections.api.map.primitive.ImmutableIntIntMap; +import org.eclipse.collections.api.map.primitive.MutableIntIntMap; +import org.eclipse.collections.api.map.primitive.MutableObjectDoubleMap; +import org.eclipse.collections.impl.factory.primitive.IntIntMaps; +import org.eclipse.collections.impl.factory.primitive.ObjectDoubleMaps; public class PrimitiveMaps { diff --git a/libraries/pom.xml b/libraries/pom.xml index a3a87876d1..7823732224 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -385,21 +385,6 @@ eclipse-collections ${eclipse-collections.version}
- - net.sf.trove4j - trove4j - 3.0.2 - - - it.unimi.dsi - fastutil - 8.1.0 - - - colt - colt - 1.2.0 - io.vavr vavr From e5f6da559f6d8c387405d2c7fc1aef2dfbd5a3f2 Mon Sep 17 00:00:00 2001 From: Johan Janssen Date: Wed, 13 Mar 2019 14:26:53 +0100 Subject: [PATCH 326/496] Moved tests to core-kotlin-2 (#6522) * Kotlin split list in pairs examples. * Renamed some items. * Moved test. --- .../src/test/kotlin/com/baeldung/splitting/SplittingTest.kt | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {core-kotlin => core-kotlin-2}/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt (100%) diff --git a/core-kotlin/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt similarity index 100% rename from core-kotlin/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt rename to core-kotlin-2/src/test/kotlin/com/baeldung/splitting/SplittingTest.kt From cd57889230a3cab66f1904e32bbda48ba205216d Mon Sep 17 00:00:00 2001 From: Eugen Paraschiv Date: Wed, 13 Mar 2019 17:29:19 +0200 Subject: [PATCH 327/496] maven cleanup --- spring-data-rest/pom.xml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spring-data-rest/pom.xml b/spring-data-rest/pom.xml index 772d6f2553..e563a6a3b5 100644 --- a/spring-data-rest/pom.xml +++ b/spring-data-rest/pom.xml @@ -2,8 +2,8 @@ 4.0.0 - com.baeldung spring-data-rest + 1.0 spring-data-rest jar @@ -40,11 +40,7 @@ org.xerial sqlite-jdbc - ${sqlite.version} - @@ -53,8 +49,6 @@ com.baeldung.SpringDataRestApplication - 3.25.2 - 2.1.0.RELEASE From 47e617fc39ba62cbfbda09f19d1b5d8764668801 Mon Sep 17 00:00:00 2001 From: cdjole Date: Wed, 13 Mar 2019 16:31:14 +0100 Subject: [PATCH 328/496] Method inlining example. (#6520) * Method inlining example. * Test added --- .../inlining/ConsecutiveNumbersSum.java | 19 ++++++++++++++++ .../baeldung/inlining/InliningExample.java | 16 ++++++++++++++ .../ConsecutiveNumbersSumUnitTest.java | 22 +++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java create mode 100644 core-java/src/main/java/com/baeldung/inlining/InliningExample.java create mode 100644 core-java/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java diff --git a/core-java/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java b/core-java/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java new file mode 100644 index 0000000000..7de642f1c0 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java @@ -0,0 +1,19 @@ +package com.baeldung.inlining; + +public class ConsecutiveNumbersSum { + + private long totalSum; + private int totalNumbers; + + public ConsecutiveNumbersSum(int totalNumbers) { + this.totalNumbers = totalNumbers; + } + + public long getTotalSum() { + totalSum = 0; + for (int i = 1; i <= totalNumbers; i++) { + totalSum += i; + } + return totalSum; + } +} diff --git a/core-java/src/main/java/com/baeldung/inlining/InliningExample.java b/core-java/src/main/java/com/baeldung/inlining/InliningExample.java new file mode 100644 index 0000000000..4c1802d0e4 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/inlining/InliningExample.java @@ -0,0 +1,16 @@ +package com.baeldung.inlining; + +public class InliningExample { + + public static final int NUMBERS_OF_ITERATIONS = 15000; + + public static void main(String[] args) { + for (int i = 1; i < NUMBERS_OF_ITERATIONS; i++) { + calculateSum(i); + } + } + + private static long calculateSum(int n) { + return new ConsecutiveNumbersSum(n).getTotalSum(); + } +} diff --git a/core-java/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java b/core-java/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java new file mode 100644 index 0000000000..8e4b0353e6 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.inlining; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ConsecutiveNumbersSumUnitTest { + + private static final int TOTAL_NUMBERS = 10; + + @Test + public void givenTotalIntegersNumber_whenSumCalculated_thenEquals() { + ConsecutiveNumbersSum consecutiveNumbersSum = new ConsecutiveNumbersSum(TOTAL_NUMBERS); + long expectedSum = calculateExpectedSum(TOTAL_NUMBERS); + + assertEquals(expectedSum, consecutiveNumbersSum.getTotalSum()); + } + + private long calculateExpectedSum(int totalNumbers) { + return totalNumbers * (totalNumbers + 1) / 2; + } +} From 895aad42f97d967284fa8e11f55d0cb9c1ef5be5 Mon Sep 17 00:00:00 2001 From: nguyennamthai Date: Wed, 13 Mar 2019 23:06:11 +0700 Subject: [PATCH 329/496] Bael 2280 (#6320) * Fix a division method mistake * BAEL-2280 Programmatically Creating Sequences with Project Reactor * BAEL-2280 Update * BAEL-2280 Update --- reactor-core/pom.xml | 16 ++--- .../reactor/creation/FibonacciState.java | 27 +++++++ .../reactor/creation/SequenceCreator.java | 14 ++++ .../reactor/creation/SequenceGenerator.java | 31 ++++++++ .../reactor/creation/SequenceHandler.java | 13 ++++ .../reactor/creation/SequenceUnitTest.java | 70 +++++++++++++++++++ 6 files changed, 163 insertions(+), 8 deletions(-) create mode 100644 reactor-core/src/main/java/com/baeldung/reactor/creation/FibonacciState.java create mode 100644 reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceCreator.java create mode 100644 reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceGenerator.java create mode 100644 reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceHandler.java create mode 100644 reactor-core/src/test/java/com/baeldung/reactor/creation/SequenceUnitTest.java diff --git a/reactor-core/pom.xml b/reactor-core/pom.xml index db9550df7b..66c634e113 100644 --- a/reactor-core/pom.xml +++ b/reactor-core/pom.xml @@ -16,7 +16,13 @@ io.projectreactor reactor-core - ${reactor-core.version} + ${reactor.version} + + + io.projectreactor + reactor-test + ${reactor.version} + test org.assertj @@ -24,16 +30,10 @@ ${assertj.version} test - - io.projectreactor - reactor-test - ${reactor-core.version} - test - - 3.1.3.RELEASE + 3.2.6.RELEASE 3.6.1 diff --git a/reactor-core/src/main/java/com/baeldung/reactor/creation/FibonacciState.java b/reactor-core/src/main/java/com/baeldung/reactor/creation/FibonacciState.java new file mode 100644 index 0000000000..291002e1f9 --- /dev/null +++ b/reactor-core/src/main/java/com/baeldung/reactor/creation/FibonacciState.java @@ -0,0 +1,27 @@ +package com.baeldung.reactor.creation; + +public class FibonacciState { + private int former; + private int latter; + + public FibonacciState(int former, int latter) { + this.former = former; + this.latter = latter; + } + + public int getFormer() { + return former; + } + + public void setFormer(int former) { + this.former = former; + } + + public int getLatter() { + return latter; + } + + public void setLatter(int latter) { + this.latter = latter; + } +} diff --git a/reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceCreator.java b/reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceCreator.java new file mode 100644 index 0000000000..fb53b1cab1 --- /dev/null +++ b/reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceCreator.java @@ -0,0 +1,14 @@ +package com.baeldung.reactor.creation; + +import reactor.core.publisher.Flux; + +import java.util.List; +import java.util.function.Consumer; + +public class SequenceCreator { + public Consumer> consumer; + + public Flux createNumberSequence() { + return Flux.create(sink -> SequenceCreator.this.consumer = items -> items.forEach(sink::next)); + } +} diff --git a/reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceGenerator.java b/reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceGenerator.java new file mode 100644 index 0000000000..44d83d06bf --- /dev/null +++ b/reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceGenerator.java @@ -0,0 +1,31 @@ +package com.baeldung.reactor.creation; + +import reactor.core.publisher.Flux; +import reactor.util.function.Tuples; + +public class SequenceGenerator { + public Flux generateFibonacciWithTuples() { + return Flux.generate( + () -> Tuples.of(0, 1), + (state, sink) -> { + sink.next(state.getT1()); + return Tuples.of(state.getT2(), state.getT1() + state.getT2()); + } + ); + } + + public Flux generateFibonacciWithCustomClass(int limit) { + return Flux.generate( + () -> new FibonacciState(0, 1), + (state, sink) -> { + sink.next(state.getFormer()); + if (state.getLatter() > limit) { + sink.complete(); + } + int temp = state.getFormer(); + state.setFormer(state.getLatter()); + state.setLatter(temp + state.getLatter()); + return state; + }); + } +} diff --git a/reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceHandler.java b/reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceHandler.java new file mode 100644 index 0000000000..a9611c63e2 --- /dev/null +++ b/reactor-core/src/main/java/com/baeldung/reactor/creation/SequenceHandler.java @@ -0,0 +1,13 @@ +package com.baeldung.reactor.creation; + +import reactor.core.publisher.Flux; + +public class SequenceHandler { + public Flux handleIntegerSequence(Flux sequence) { + return sequence.handle((number, sink) -> { + if (number % 2 == 0) { + sink.next(number / 2); + } + }); + } +} diff --git a/reactor-core/src/test/java/com/baeldung/reactor/creation/SequenceUnitTest.java b/reactor-core/src/test/java/com/baeldung/reactor/creation/SequenceUnitTest.java new file mode 100644 index 0000000000..78af1d2478 --- /dev/null +++ b/reactor-core/src/test/java/com/baeldung/reactor/creation/SequenceUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.reactor.creation; + +import org.junit.Test; +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SequenceUnitTest { + @Test + public void whenGeneratingNumbersWithTuplesState_thenFibonacciSequenceIsProduced() { + SequenceGenerator sequenceGenerator = new SequenceGenerator(); + Flux fibonacciFlux = sequenceGenerator.generateFibonacciWithTuples().take(5); + + StepVerifier.create(fibonacciFlux) + .expectNext(0, 1, 1, 2, 3) + .expectComplete() + .verify(); + } + + @Test + public void whenGeneratingNumbersWithCustomClass_thenFibonacciSequenceIsProduced() { + SequenceGenerator sequenceGenerator = new SequenceGenerator(); + + StepVerifier.create(sequenceGenerator.generateFibonacciWithCustomClass(10)) + .expectNext(0, 1, 1, 2, 3, 5, 8) + .expectComplete() + .verify(); + } + + @Test + public void whenCreatingNumbers_thenSequenceIsProducedAsynchronously() throws InterruptedException { + SequenceGenerator sequenceGenerator = new SequenceGenerator(); + List sequence1 = sequenceGenerator.generateFibonacciWithTuples().take(3).collectList().block(); + List sequence2 = sequenceGenerator.generateFibonacciWithTuples().take(4).collectList().block(); + + SequenceCreator sequenceCreator = new SequenceCreator(); + Thread producingThread1 = new Thread( + () -> sequenceCreator.consumer.accept(sequence1) + ); + Thread producingThread2 = new Thread( + () -> sequenceCreator.consumer.accept(sequence2) + ); + + List consolidated = new ArrayList<>(); + sequenceCreator.createNumberSequence().subscribe(consolidated::add); + + producingThread1.start(); + producingThread2.start(); + producingThread1.join(); + producingThread2.join(); + + assertThat(consolidated).containsExactlyInAnyOrder(0, 1, 1, 0, 1, 1, 2); + } + + @Test + public void whenHandlingNumbers_thenSequenceIsMappedAndFiltered() { + SequenceHandler sequenceHandler = new SequenceHandler(); + SequenceGenerator sequenceGenerator = new SequenceGenerator(); + Flux sequence = sequenceGenerator.generateFibonacciWithTuples().take(10); + + StepVerifier.create(sequenceHandler.handleIntegerSequence(sequence)) + .expectNext(0, 1, 4, 17) + .expectComplete() + .verify(); + } +} From 22dea679618d7e7ba460f14290643ae7015c0985 Mon Sep 17 00:00:00 2001 From: TINO Date: Wed, 13 Mar 2019 20:07:48 +0300 Subject: [PATCH 330/496] BAEL - 1060 Review comments incorporated --- .../rxjava/RxJavaHooksManualTest.java | 84 +++++++++++++++++++ .../baeldung/rxjava/RxJavaHooksUnitTest.java | 61 -------------- 2 files changed, 84 insertions(+), 61 deletions(-) create mode 100644 rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java b/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java new file mode 100644 index 0000000000..b79fa9af22 --- /dev/null +++ b/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksManualTest.java @@ -0,0 +1,84 @@ +package com.baeldung.rxjava; + +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Test; + +import io.reactivex.Observable; +import io.reactivex.plugins.RxJavaPlugins; +import io.reactivex.schedulers.Schedulers; + +public class RxJavaHooksManualTest { + + private boolean initHookCalled = false; + private boolean hookCalled = false; + + @Test + public void givenIOScheduler_whenCalled_shouldExecuteTheHooks() { + + RxJavaPlugins.setInitIoSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); + + RxJavaPlugins.setIoSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.io()) + .test(); + assertTrue(hookCalled && initHookCalled); + } + + @Test + public void givenNewThreadScheduler_whenCalled_shouldExecuteTheHook() { + + RxJavaPlugins.setInitNewThreadSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); + + RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 15) + .map(v -> v * 2) + .subscribeOn(Schedulers.newThread()) + .test(); + assertTrue(hookCalled && initHookCalled); + } + + @Test + public void givenSingleScheduler_whenCalled_shouldExecuteTheHooks() { + + RxJavaPlugins.setInitSingleSchedulerHandler((scheduler) -> { + initHookCalled = true; + return scheduler.call(); + }); + + RxJavaPlugins.setSingleSchedulerHandler((scheduler) -> { + hookCalled = true; + return scheduler; + }); + + Observable.range(1, 10) + .map(v -> v * 2) + .subscribeOn(Schedulers.single()) + .test(); + assertTrue(hookCalled && initHookCalled); + + } + + @After + public void reset() { + hookCalled = false; + initHookCalled = false; + RxJavaPlugins.reset(); + } +} diff --git a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java b/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java index 79b80f71ab..dd4287a4a9 100644 --- a/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java +++ b/rxjava-2/src/test/java/com/baeldung/rxjava/RxJavaHooksUnitTest.java @@ -235,67 +235,6 @@ public class RxJavaHooksUnitTest { assertTrue(hookCalled && initHookCalled); } - @Test - public void givenIOScheduler_whenCalled_shouldExecuteTheHooks() { - - RxJavaPlugins.setInitIoSchedulerHandler((scheduler) -> { - initHookCalled = true; - return scheduler.call(); - }); - - RxJavaPlugins.setIoSchedulerHandler((scheduler) -> { - hookCalled = true; - return scheduler; - }); - - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.io()) - .test(); - assertTrue(hookCalled && initHookCalled); - } - - @Test - public void givenNewThreadScheduler_whenCalled_shouldExecuteTheHook() { - - RxJavaPlugins.setInitNewThreadSchedulerHandler((scheduler) -> { - initHookCalled = true; - return scheduler.call(); - }); - - RxJavaPlugins.setNewThreadSchedulerHandler((scheduler) -> { - hookCalled = true; - return scheduler; - }); - - Observable.range(1, 15) - .map(v -> v * 2) - .subscribeOn(Schedulers.newThread()) - .test(); - assertTrue(hookCalled && initHookCalled); - } - - @Test - public void givenSingleScheduler_whenCalled_shouldExecuteTheHooks() { - - RxJavaPlugins.setInitSingleSchedulerHandler((scheduler) -> { - initHookCalled = true; - return scheduler.call(); - }); - - RxJavaPlugins.setSingleSchedulerHandler((scheduler) -> { - hookCalled = true; - return scheduler; - }); - - Observable.range(1, 10) - .map(v -> v * 2) - .subscribeOn(Schedulers.single()) - .test(); - assertTrue(hookCalled && initHookCalled); - - } - @After public void reset() { initHookCalled = false; From ddd3591e0b11a0d04c469e1c5271b0c43d0228cb Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Wed, 13 Mar 2019 23:10:59 +0530 Subject: [PATCH 331/496] BAEL-13321 Fixed test-data creation logic in live test --- .../com/baeldung/projection/SpringDataProjectionLiveTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java b/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java index ad219ccd53..274ae3bc1d 100644 --- a/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java +++ b/spring-data-rest/src/test/java/com/baeldung/projection/SpringDataProjectionLiveTest.java @@ -37,7 +37,7 @@ public class SpringDataProjectionLiveTest { @Before public void setup() { - if (bookRepo.findById(1L) == null) { + if (!bookRepo.findById(1L).isPresent()) { Book book = new Book("Animal Farm"); book.setIsbn("978-1943138425"); book = bookRepo.save(book); From 64418480e70e0eb4ca1d614edf11b2902c7b9463 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:09:25 +0800 Subject: [PATCH 332/496] Update README.md --- spring-security-mvc-ldap/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-security-mvc-ldap/README.md b/spring-security-mvc-ldap/README.md index fe6a667c40..ac080c138d 100644 --- a/spring-security-mvc-ldap/README.md +++ b/spring-security-mvc-ldap/README.md @@ -6,7 +6,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Article: - [Spring Security - security none, filters none, access permitAll](http://www.baeldung.com/security-none-filters-none-access-permitAll) -- [Spring Security Basic Authentication](http://www.baeldung.com/spring-security-basic-authentication) - [Intro to Spring Security LDAP](http://www.baeldung.com/spring-security-ldap) ### Notes From d2196736f9cd30fad1627ab6f122c01132279dd2 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:09:57 +0800 Subject: [PATCH 333/496] Update README.md --- spring-all/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-all/README.md b/spring-all/README.md index 81dd435007..82d876768e 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -22,7 +22,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [A Guide to the Spring Task Scheduler](http://www.baeldung.com/spring-task-scheduler) - [Guide to Spring Retry](http://www.baeldung.com/spring-retry) - [Custom Scope in Spring](http://www.baeldung.com/spring-custom-scope) -- [New in Guava 21 common.util.concurrent](http://www.baeldung.com/guava-21-util-concurrent) - [A CLI with Spring Shell](http://www.baeldung.com/spring-shell-cli) - [JasperReports with Spring](http://www.baeldung.com/spring-jasper) - [Model, ModelMap, and ModelView in Spring MVC](http://www.baeldung.com/spring-mvc-model-model-map-model-view) From 801605392b404134c2bf6177d2f7543d0f04f7ff Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:11:14 +0800 Subject: [PATCH 334/496] Update README.md --- spring-mvc-java/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md index 851a3689ab..497b0f4c1f 100644 --- a/spring-mvc-java/README.md +++ b/spring-mvc-java/README.md @@ -29,6 +29,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [A Quick Example of Spring Websockets’ @SendToUser Annotation](http://www.baeldung.com/spring-websockets-sendtouser) - [Using Spring ResponseEntity to Manipulate the HTTP Response](http://www.baeldung.com/spring-response-entity) - [Using Spring @ResponseStatus to Set HTTP Status Code](http://www.baeldung.com/spring-response-status) -- [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) - [Spring MVC Tutorial](https://www.baeldung.com/spring-mvc-tutorial) - [Working with Date Parameters in Spring](https://www.baeldung.com/spring-date-parameters) From f6de1aff0ab620ba36dd148db52e6a875632aa20 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:11:50 +0800 Subject: [PATCH 335/496] Update README.MD --- spring-session/spring-session-jdbc/README.MD | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-session/spring-session-jdbc/README.MD b/spring-session/spring-session-jdbc/README.MD index 9293dfc953..94fd1cd3e7 100644 --- a/spring-session/spring-session-jdbc/README.MD +++ b/spring-session/spring-session-jdbc/README.MD @@ -2,5 +2,3 @@ This module is for Spring Session with JDBC tutorial. Jira BAEL-1911 ### Relevant Articles: - -- [Spring Session with JDBC](http://www.baeldung.com/spring-session-jdbc) From d66aa3c28df5a4bac6a306687a2a1f12fc73d040 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:12:08 +0800 Subject: [PATCH 336/496] Rename README.MD to README.md --- spring-session/spring-session-jdbc/{README.MD => README.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spring-session/spring-session-jdbc/{README.MD => README.md} (100%) diff --git a/spring-session/spring-session-jdbc/README.MD b/spring-session/spring-session-jdbc/README.md similarity index 100% rename from spring-session/spring-session-jdbc/README.MD rename to spring-session/spring-session-jdbc/README.md From 7d3486e19af3603f5814a0485920a4fe573fffaf Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:12:25 +0800 Subject: [PATCH 337/496] Update README.md --- spring-session/spring-session-redis/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-session/spring-session-redis/README.md b/spring-session/spring-session-redis/README.md index 5e9304d778..5865913711 100644 --- a/spring-session/spring-session-redis/README.md +++ b/spring-session/spring-session-redis/README.md @@ -3,4 +3,3 @@ ## Spring Session Examples ### Relevant Articles: -- [Guide to Spring Session](http://www.baeldung.com/spring-session) From 5b89544fb72fd85e0f3532a99d077ae4a58d8ca7 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:16:46 +0800 Subject: [PATCH 338/496] Update README.md --- core-java/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/core-java/README.md b/core-java/README.md index ff20f736e0..e1325ab29f 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -29,7 +29,6 @@ - [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid) - [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle) - [Class Loaders in Java](http://www.baeldung.com/java-classloaders) -- [Double-Checked Locking with Singleton](http://www.baeldung.com/java-singleton-double-checked-locking) - [Guide to Java Clock Class](http://www.baeldung.com/java-clock) - [Importance of Main Manifest Attribute in a Self-Executing JAR](http://www.baeldung.com/java-jar-executable-manifest-main-class) - [Java Global Exception Handler](http://www.baeldung.com/java-global-exception-handler) @@ -51,4 +50,3 @@ - [Finding Leap Years in Java](https://www.baeldung.com/java-leap-year) - [Java Bitwise Operators](https://www.baeldung.com/java-bitwise-operators) - [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) -- [Sending Emails with Java](https://www.baeldung.com/java-email) From 9a41f5983dcdad5170b6b0ff6f602ee681497e18 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:17:15 +0800 Subject: [PATCH 339/496] Update README.md --- httpclient/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/httpclient/README.md b/httpclient/README.md index 7c5122c5b8..87fb38706d 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -12,7 +12,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [HttpClient 4 – Cancel / Abort Request](http://www.baeldung.com/httpclient-cancel-request) - [HttpClient 4 Cookbook](http://www.baeldung.com/httpclient4) - [Unshorten URLs with HttpClient](http://www.baeldung.com/unshorten-url-httpclient) -- [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl) - [HttpClient 4 – Follow Redirects for POST](http://www.baeldung.com/httpclient-redirect-on-http-post) - [Custom HTTP Header with the HttpClient](http://www.baeldung.com/httpclient-custom-http-header) - [HttpClient Basic Authentication](http://www.baeldung.com/httpclient-4-basic-authentication) From 608db123a8b2e6a5ff445a7900dbe9f7eae7a7d1 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:17:39 +0800 Subject: [PATCH 340/496] Update README.md --- spring-5-mvc/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-5-mvc/README.md b/spring-5-mvc/README.md index fa9d48ab72..7e83077f54 100644 --- a/spring-5-mvc/README.md +++ b/spring-5-mvc/README.md @@ -2,4 +2,3 @@ - [Spring Boot and Kotlin](http://www.baeldung.com/spring-boot-kotlin) - [Spring MVC Streaming and SSE Request Processing](https://www.baeldung.com/spring-mvc-sse-streams) - [Overview and Need for DelegatingFilterProxy in Spring](https://www.baeldung.com/spring-delegating-filter-proxy) -- [A Controller, Service and DAO Example with Spring Boot and JSF](https://www.baeldung.com/jsf-spring-boot-controller-service-dao) From fa3020aa3e169f9faa3da1c830c1c93cb04ffce2 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:18:09 +0800 Subject: [PATCH 341/496] Update README.md --- spring-rest-simple/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-rest-simple/README.md b/spring-rest-simple/README.md index 179e556202..882d0ac301 100644 --- a/spring-rest-simple/README.md +++ b/spring-rest-simple/README.md @@ -3,6 +3,5 @@ - [Guide to UriComponentsBuilder in Spring](http://www.baeldung.com/spring-uricomponentsbuilder) - [Returning Custom Status Codes from Spring Controllers](http://www.baeldung.com/spring-mvc-controller-custom-http-status-code) - [Spring RequestMapping](http://www.baeldung.com/spring-requestmapping) -- [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) - [Spring and Apache FileUpload](http://www.baeldung.com/spring-apache-file-upload) - [Test a REST API with curl](http://www.baeldung.com/curl-rest) From 97ec5d69562dbe59657828bcf7dbe3d4bf9f7c2e Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:18:33 +0800 Subject: [PATCH 342/496] Update README.md --- gradle/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/gradle/README.md b/gradle/README.md index a1f5c74c57..14e460f225 100644 --- a/gradle/README.md +++ b/gradle/README.md @@ -3,5 +3,4 @@ - [Writing Custom Gradle Plugins](http://www.baeldung.com/gradle-create-plugin) - [Creating a Fat Jar in Gradle](http://www.baeldung.com/gradle-fat-jar) - [A Custom Task in Gradle](http://www.baeldung.com/gradle-custom-task) -- [Kotlin Dependency Injection with Kodein](http://www.baeldung.com/kotlin-kodein-dependency-injection) - [Using JUnit 5 with Gradle](https://www.baeldung.com/junit-5-gradle) From 17a5f6f6ed34d755c7ebca340f63f1514d80c200 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:19:23 +0800 Subject: [PATCH 343/496] Update README.md --- spring-rest-full/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-rest-full/README.md b/spring-rest-full/README.md index ed6df1675f..e0d3a70626 100644 --- a/spring-rest-full/README.md +++ b/spring-rest-full/README.md @@ -12,7 +12,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [Project Configuration with Spring](http://www.baeldung.com/project-configuration-with-spring) - [Metrics for your Spring REST API](http://www.baeldung.com/spring-rest-api-metrics) -- [Bootstrap a Web Application with Spring 5](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) - [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic) From e6e26f6947cab6a028aad48bbd7bbdc42ff0cc99 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:19:56 +0800 Subject: [PATCH 344/496] Update README.md --- spring-boot-bootstrap/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/spring-boot-bootstrap/README.md b/spring-boot-bootstrap/README.md index 70fcd90118..6a88f25bd7 100644 --- a/spring-boot-bootstrap/README.md +++ b/spring-boot-bootstrap/README.md @@ -1,6 +1,5 @@ ### Relevant Articles: - [Spring Boot Tutorial – Bootstrap a Simple Application](http://www.baeldung.com/spring-boot-start) -- [Spring Boot Dependency Management with a Custom Parent](http://www.baeldung.com/spring-boot-dependency-management-custom-parent) - [Thin JARs with Spring Boot](http://www.baeldung.com/spring-boot-thin-jar) - [Deploying a Spring Boot Application to Cloud Foundry](https://www.baeldung.com/spring-boot-app-deploy-to-cloud-foundry) - [Deploy a Spring Boot Application to Google App Engine](https://www.baeldung.com/spring-boot-google-app-engine) From c1ae56b3bfdb13463be7a0e6320d39001e41a2e6 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:21:46 +0800 Subject: [PATCH 345/496] Update README.md --- logging-modules/log4j/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/logging-modules/log4j/README.md b/logging-modules/log4j/README.md index 9f4184ccba..a7a7ea9643 100644 --- a/logging-modules/log4j/README.md +++ b/logging-modules/log4j/README.md @@ -1,7 +1,5 @@ ### Relevant Articles: - [Introduction to Java Logging](http://www.baeldung.com/java-logging-intro) - [Introduction to SLF4J](http://www.baeldung.com/slf4j-with-log4j2-logback) -- [Generate equals() and hashCode() with Eclipse](http://www.baeldung.com/java-eclipse-equals-and-hashcode) -- [Introduction to SLF4J](http://www.baeldung.com/slf4j-with-log4j2-logback) - [A Guide to Rolling File Appenders](http://www.baeldung.com/java-logging-rolling-file-appenders) - [Logging Exceptions Using SLF4J](https://www.baeldung.com/slf4j-log-exceptions) From 8f5c4b0c891205d2886979a74049c287b38abcb3 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:23:29 +0800 Subject: [PATCH 346/496] Update README.md --- google-web-toolkit/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/google-web-toolkit/README.md b/google-web-toolkit/README.md index 65264375bc..3526fe9962 100644 --- a/google-web-toolkit/README.md +++ b/google-web-toolkit/README.md @@ -1,3 +1,2 @@ ### Relevant Articles: - [Introduction to GWT](http://www.baeldung.com/gwt) -- [Quick Use of FilenameFilter](http://www.baeldung.com/java-filename-filter) From d8931291f742ad958a650e9481e61275272f8874 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:26:38 +0800 Subject: [PATCH 347/496] Delete README.md --- .../src/main/java/com/baeldung/enums/README.md | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 core-java-lang-syntax/src/main/java/com/baeldung/enums/README.md diff --git a/core-java-lang-syntax/src/main/java/com/baeldung/enums/README.md b/core-java-lang-syntax/src/main/java/com/baeldung/enums/README.md deleted file mode 100644 index 6ccfa725f5..0000000000 --- a/core-java-lang-syntax/src/main/java/com/baeldung/enums/README.md +++ /dev/null @@ -1,2 +0,0 @@ -### Relevant Articles: -- [A Guide to Java Enums](http://www.baeldung.com/a-guide-to-java-enums) From 00dc9ff6850c21c46e3688462353451a91fbf1ae Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:29:41 +0800 Subject: [PATCH 348/496] Update README.md --- guava-modules/guava-18/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/guava-modules/guava-18/README.md b/guava-modules/guava-18/README.md index 9924d7c16f..fd5de4170a 100644 --- a/guava-modules/guava-18/README.md +++ b/guava-modules/guava-18/README.md @@ -4,9 +4,5 @@ ### Relevant Articles: -- [Guava Collections Cookbook](http://www.baeldung.com/guava-collections) -- [Guava Ordering Cookbook](http://www.baeldung.com/guava-order) - [Guava Functional Cookbook](http://www.baeldung.com/guava-functions-predicates) -- [Hamcrest Collections Cookbook](http://www.baeldung.com/hamcrest-collections-arrays) -- [Partition a List in Java](http://www.baeldung.com/java-list-split) - [Guava 18: What’s New?](http://www.baeldung.com/whats-new-in-guava-18) From 78fe53192c452479665c2d74de1d18646bb6a6a3 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:31:00 +0800 Subject: [PATCH 349/496] Update README.md --- apache-fop/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apache-fop/README.md b/apache-fop/README.md index 772681ad57..1e734a5f36 100644 --- a/apache-fop/README.md +++ b/apache-fop/README.md @@ -3,7 +3,3 @@ ## Core Java Cookbooks and Examples ### Relevant Articles: -- [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list) -- [Java - Reading a Large File Efficiently](http://www.baeldung.com/java-read-lines-large-file) -- [Java InputStream to String](http://www.baeldung.com/convert-input-stream-to-string) - From 0bb77443469b995c8ff1008fa9e71ee6e6b443c5 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:31:42 +0800 Subject: [PATCH 350/496] Update README.md --- core-java-lang-oop/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-lang-oop/README.md b/core-java-lang-oop/README.md index 200415fe21..970a8d44b1 100644 --- a/core-java-lang-oop/README.md +++ b/core-java-lang-oop/README.md @@ -5,7 +5,6 @@ ### Relevant Articles: - [Guide to hashCode() in Java](http://www.baeldung.com/java-hashcode) - [A Guide to the Static Keyword in Java](http://www.baeldung.com/java-static) -- [A Guide to Java Initialization](http://www.baeldung.com/java-initialization) - [Polymorphism in Java](http://www.baeldung.com/java-polymorphism) - [Method Overloading and Overriding in Java](http://www.baeldung.com/java-method-overload-override) - [How to Make a Deep Copy of an Object in Java](http://www.baeldung.com/java-deep-copy) From 52dbb4a9f8ee484e5acde21e4608f53265c7abfe Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:32:58 +0800 Subject: [PATCH 351/496] Update README.md --- core-java-io/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-io/README.md b/core-java-io/README.md index 22901b22d5..05b9165147 100644 --- a/core-java-io/README.md +++ b/core-java-io/README.md @@ -30,7 +30,6 @@ - [Download a File From an URL in Java](http://www.baeldung.com/java-download-file) - [Create a Symbolic Link with Java](http://www.baeldung.com/java-symlink) - [Quick Use of FilenameFilter](http://www.baeldung.com/java-filename-filter) -- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) - [Read a File into an ArrayList](https://www.baeldung.com/java-file-to-arraylist) - [Guide to Java OutputStream](https://www.baeldung.com/java-outputstream) - [Reading a CSV File into an Array](https://www.baeldung.com/java-csv-file-array) From b7e197ee6459cad56c5fb4b1cc629a9dbba65cac Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:40:57 +0800 Subject: [PATCH 352/496] Update README.md --- testing-modules/mocks/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/testing-modules/mocks/README.md b/testing-modules/mocks/README.md index 2b24ed8536..3cb20dcf92 100644 --- a/testing-modules/mocks/README.md +++ b/testing-modules/mocks/README.md @@ -1,8 +1,4 @@ ## Relevant articles: -- [JMockit Advanced Usage](http://www.baeldung.com/jmockit-advanced-usage) -- [A Guide to JMockit Expectations](http://www.baeldung.com/jmockit-expectations) -- [JMockit 101](http://www.baeldung.com/jmockit-101) -- [Mockito vs EasyMock vs JMockit](http://www.baeldung.com/mockito-vs-easymock-vs-jmockit) - [EasyMock Argument Matchers](http://www.baeldung.com/easymock-argument-matchers) - [Mock Static Method using JMockit](https://www.baeldung.com/jmockit-static-method) From e7d06b00044b05bb3434e3ee3aae27b4e989d67d Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:41:20 +0800 Subject: [PATCH 353/496] Update README.md --- testing-modules/mocks/jmockit/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/testing-modules/mocks/jmockit/README.md b/testing-modules/mocks/jmockit/README.md index 3063fdc31d..0e44b93d6e 100644 --- a/testing-modules/mocks/jmockit/README.md +++ b/testing-modules/mocks/jmockit/README.md @@ -6,5 +6,4 @@ ### Relevant Articles: - [JMockit 101](http://www.baeldung.com/jmockit-101) - [A Guide to JMockit Expectations](http://www.baeldung.com/jmockit-expectations) -- [JMockit Advanced Topics](http://www.baeldung.com/jmockit-advanced-topics) - [JMockit Advanced Usage](http://www.baeldung.com/jmockit-advanced-usage) From 6a7e36193b973e1c44951d176eae27784bbada69 Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:42:26 +0800 Subject: [PATCH 354/496] Delete README.md --- noexception/README.md | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 noexception/README.md diff --git a/noexception/README.md b/noexception/README.md deleted file mode 100644 index 9dd4c11190..0000000000 --- a/noexception/README.md +++ /dev/null @@ -1,2 +0,0 @@ -### Relevant Articles: -- [Introduction to NoException](http://www.baeldung.com/introduction-to-noexception) From e681a5447a76236a4b7ffcaa3052a69d0ef3202f Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:44:44 +0800 Subject: [PATCH 355/496] Delete README.md --- testing-modules/junit5-migration/README.md | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 testing-modules/junit5-migration/README.md diff --git a/testing-modules/junit5-migration/README.md b/testing-modules/junit5-migration/README.md deleted file mode 100644 index 5fe7fc1f16..0000000000 --- a/testing-modules/junit5-migration/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: -- [JUnit4 -> JUnit5 migration guide](http://www.baeldung.com/junit4-junit5-migration-guide) - From 6869885cf415e7268adca1ff1426cb8dd2d47993 Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Wed, 13 Mar 2019 19:45:09 +0000 Subject: [PATCH 356/496] BAEL-2522 Moved to another module --- java-dates-2/.gitignore | 29 ++++++++++ java-dates-2/pom.xml | 55 +++++++++++++++++++ ...XmlGregorianCalendarConverterUnitTest.java | 6 +- 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 java-dates-2/.gitignore create mode 100644 java-dates-2/pom.xml rename java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java => java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java (85%) diff --git a/java-dates-2/.gitignore b/java-dates-2/.gitignore new file mode 100644 index 0000000000..6471aabbcf --- /dev/null +++ b/java-dates-2/.gitignore @@ -0,0 +1,29 @@ +*.class + +0.* + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* +.resourceCache + +# Packaged files # +*.jar +*.war +*.ear + +# Files generated by integration tests +*.txt +backup-pom.xml +/bin/ +/temp + +#IntelliJ specific +.idea/ +*.iml + +#jenv +.java-version \ No newline at end of file diff --git a/java-dates-2/pom.xml b/java-dates-2/pom.xml new file mode 100644 index 0000000000..93216e3ffa --- /dev/null +++ b/java-dates-2/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + com.baeldung + java-dates-2 + 0.1.0-SNAPSHOT + jar + java-dates-2 + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + java-dates-2 + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + + 3.6.1 + 1.9 + 1.9 + + diff --git a/java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java b/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java similarity index 85% rename from java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java rename to java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java index 7fe1cd36a1..34510a3167 100644 --- a/java-dates/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterTest.java +++ b/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java @@ -7,11 +7,9 @@ import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import java.time.LocalDate; -import static com.baeldung.xmlgregoriancalendar.XmlGregorianCalendarConverter.fromLocalDate; -import static com.baeldung.xmlgregoriancalendar.XmlGregorianCalendarConverter.fromXMLGregorianCalendar; import static org.assertj.core.api.Assertions.assertThat; -public class XmlGregorianCalendarConverterTest { +public class XmlGregorianCalendarConverterUnitTest { @Test public void fromLocalDateToXMLGregorianCalendar() throws DatatypeConfigurationException { @@ -32,5 +30,5 @@ public class XmlGregorianCalendarConverterTest { assertThat(localDate.getMonthValue()).isEqualTo(xmlGregorianCalendar.getMonth()); assertThat(localDate.getDayOfMonth()).isEqualTo(xmlGregorianCalendar.getDay()); } - + } From 557049bbd1d560b16ab5182639e01856b29e742f Mon Sep 17 00:00:00 2001 From: charlesgonzales <39999268+charlesgonzales@users.noreply.github.com> Date: Thu, 14 Mar 2019 03:45:40 +0800 Subject: [PATCH 357/496] Update README.md --- jjwt/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/jjwt/README.md b/jjwt/README.md index 54a5226056..ed18363dfc 100644 --- a/jjwt/README.md +++ b/jjwt/README.md @@ -42,7 +42,6 @@ Available commands (assumes httpie - https://github.com/jkbrzt/httpie): Parse passed in JWT enforcing the 'iss' registered claim and the 'hasMotorcycle' custom claim ``` -The Baeldung post that compliments this repo can be found [here](http://www.baeldung.com/) ## Relevant articles: From bde5b5f559adbfd5508a23c24fb54d977339806e Mon Sep 17 00:00:00 2001 From: mikr Date: Sun, 10 Mar 2019 19:28:09 +0100 Subject: [PATCH 358/496] BAEL-2562 New section in Generics article --- .../src/main/java/com/baeldung/generics/Generics.java | 7 +++++++ .../java/com/baeldung/generics/GenericsUnitTest.java | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/core-java-lang-syntax/src/main/java/com/baeldung/generics/Generics.java b/core-java-lang-syntax/src/main/java/com/baeldung/generics/Generics.java index e0536ca02e..1c4082c58b 100644 --- a/core-java-lang-syntax/src/main/java/com/baeldung/generics/Generics.java +++ b/core-java-lang-syntax/src/main/java/com/baeldung/generics/Generics.java @@ -1,5 +1,6 @@ package com.baeldung.generics; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.Function; @@ -28,4 +29,10 @@ public class Generics { buildings.forEach(Building::paint); } + public static List createList(int a) { + List list = new ArrayList<>(); + list.add(a); + return list; + } + } \ No newline at end of file diff --git a/core-java-lang-syntax/src/test/java/com/baeldung/generics/GenericsUnitTest.java b/core-java-lang-syntax/src/test/java/com/baeldung/generics/GenericsUnitTest.java index aca0b182a0..0bdf0afc15 100644 --- a/core-java-lang-syntax/src/test/java/com/baeldung/generics/GenericsUnitTest.java +++ b/core-java-lang-syntax/src/test/java/com/baeldung/generics/GenericsUnitTest.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.List; import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.fail; @@ -66,4 +67,12 @@ public class GenericsUnitTest { } } + @Test + public void givenAnInt_whenAddedToAGenericIntegerList_thenAListItemCanBeAssignedToAnInt() { + int number = 7; + List list = Generics.createList(number); + int otherNumber = list.get(0); + assertThat(otherNumber, is(number)); + } + } \ No newline at end of file From f90dd073cb63e823d6563826d4d5b12aadaed49c Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Thu, 14 Mar 2019 09:32:06 +0000 Subject: [PATCH 359/496] BAEL-2522 - Updated parent pom with the new module --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 58d57ade05..ac1273b28d 100644 --- a/pom.xml +++ b/pom.xml @@ -440,6 +440,7 @@ java-collections-conversions java-collections-maps + java-dates-2 java-lite java-numbers From 05e3bf3a828f6d9c056de42b47bf8e642a4a4c3f Mon Sep 17 00:00:00 2001 From: jarpz Date: Thu, 14 Mar 2019 14:54:14 -0500 Subject: [PATCH 360/496] How to return 404 with Spring WebFlux (#6509) * feat(response-status): return response http status * fix(style): improve code style * BAEL-2716: How to return 404 with Spring WebFlux * style: apply baeldung intellij formatter * Delete .gitignore * config: remove gitignore & remove unused maven plugin --- spring-5-webflux/pom.xml | 70 +++++++++++++++++++ .../ResponseStatusController.java | 64 +++++++++++++++++ .../SpringResponseStatusApp.java | 12 ++++ .../ResponseStatusControllerTests.java | 70 +++++++++++++++++++ 4 files changed, 216 insertions(+) create mode 100644 spring-5-webflux/pom.xml create mode 100644 spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java create mode 100644 spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/SpringResponseStatusApp.java create mode 100644 spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerTests.java diff --git a/spring-5-webflux/pom.xml b/spring-5-webflux/pom.xml new file mode 100644 index 0000000000..d7fb7b7930 --- /dev/null +++ b/spring-5-webflux/pom.xml @@ -0,0 +1,70 @@ + + + + 4.0.0 + + com.baeldung + spring-5-webflux + 1.0-SNAPSHOT + + spring-5-webflux + + http://www.baeldung.com + + + UTF-8 + 1.8 + 1.8 + 2.0.2.RELEASE + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-webflux + + + + org.projectlombok + lombok + + + + org.springframework.boot + spring-boot-starter-test + test + + + + junit + junit + test + + + + + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + + diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java new file mode 100644 index 0000000000..bc4f628ab1 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/ResponseStatusController.java @@ -0,0 +1,64 @@ +package com.baeldung.spring.responsestatus; + +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; + +@RequestMapping("/statuses") +@RestController +public class ResponseStatusController { + + @GetMapping(value = "/ok", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public Flux ok() { + return Flux.just("ok"); + } + + @GetMapping(value = "/no-content", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + @ResponseStatus(HttpStatus.NO_CONTENT) + public Flux noContent() { + return Flux.empty(); + } + + @GetMapping(value = "/accepted", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) + public Flux accepted(ServerHttpResponse response) { + response.setStatusCode(HttpStatus.ACCEPTED); + return Flux.just("accepted"); + } + + @GetMapping(value = "/bad-request") + public Mono badRequest() { + return Mono.error(new IllegalArgumentException()); + } + + @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "Illegal arguments") + @ExceptionHandler(IllegalArgumentException.class) + public void illegalArgument() { + + } + + @GetMapping(value = "/unauthorized") + public ResponseEntity> unathorized() { + return ResponseEntity + .status(HttpStatus.UNAUTHORIZED) + .header("X-Reason", "user-invalid") + .body(Mono.just("unauthorized")); + } + + @Bean + public RouterFunction notFound() { + return RouterFunctions.route(GET("/statuses/not-found"), request -> ServerResponse + .notFound() + .build()); + } + +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/SpringResponseStatusApp.java b/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/SpringResponseStatusApp.java new file mode 100644 index 0000000000..1d90511d9d --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/responsestatus/SpringResponseStatusApp.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.responsestatus; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringResponseStatusApp { + + public static void main(String[] args) { + SpringApplication.run(SpringResponseStatusApp.class, args); + } +} diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerTests.java b/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerTests.java new file mode 100644 index 0000000000..5112c8ceb2 --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerTests.java @@ -0,0 +1,70 @@ +package com.baeldung.spring.responsestatus; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class ResponseStatusControllerTests { + + @Autowired + private WebTestClient testClient; + + @Test + public void whenCallRest_thenStatusIsOk() { + testClient.get() + .uri("/statuses/ok") + .exchange() + .expectStatus() + .isOk(); + } + + @Test + public void whenCallRest_thenStatusIsNoContent() { + testClient.get() + .uri("/statuses/no-content") + .exchange() + .expectStatus() + .isNoContent(); + } + + @Test + public void whenCallRest_thenStatusIsAccepted() { + testClient.get() + .uri("/statuses/accepted") + .exchange() + .expectStatus() + .isAccepted(); + } + + @Test + public void whenCallRest_thenStatusIsBadRequest() { + testClient.get() + .uri("/statuses/bad-request") + .exchange() + .expectStatus() + .isBadRequest(); + } + + @Test + public void whenCallRest_thenStatusIsUnauthorized() { + testClient.get() + .uri("/statuses/unauthorized") + .exchange() + .expectStatus() + .isUnauthorized(); + } + + @Test + public void whenCallRest_thenStatusIsNotFound() { + testClient.get() + .uri("/statuses/not-found") + .exchange() + .expectStatus() + .isNotFound(); + } +} From b3fc27088b6513513fee6b3d9b4c524bda9cd02e Mon Sep 17 00:00:00 2001 From: dionisPrifti Date: Thu, 14 Mar 2019 20:55:45 +0100 Subject: [PATCH 361/496] Bael 2709 (#6527) * BAEL-2709: Implementing example for Spring Boot Hibernate. * BAEL-2709: Changed test name. --- .../application/tests/BookServiceUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothibernate/application/tests/BookServiceUnitTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothibernate/application/tests/BookServiceUnitTest.java index fe8bb339a4..655a852001 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothibernate/application/tests/BookServiceUnitTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springboothibernate/application/tests/BookServiceUnitTest.java @@ -19,7 +19,7 @@ public class BookServiceUnitTest { private BookService bookService; @Test - public void test() { + public void whenApplicationStarts_thenHibernateCreatesInitialRecords() { List books = bookService.list(); Assert.assertEquals(books.size(), 3); From dc72b8b39755a78670bf790d451001b331ea67bb Mon Sep 17 00:00:00 2001 From: Kumar Chandrakant Date: Fri, 15 Mar 2019 11:22:27 +0530 Subject: [PATCH 362/496] Adding source code for the tutorial tracked under BAEL-2759 (#6533) --- pom.xml | 5 ++ tensorflow-java/.gitignore | 6 +++ tensorflow-java/README.md | 3 ++ tensorflow-java/pom.xml | 52 +++++++++++++++++++ .../baeldung/tensorflow/TensorflowGraph.java | 41 +++++++++++++++ .../tensorflow/TensorflowSavedModel.java | 14 +++++ .../src/main/python/tensorflowGraph.py | 16 ++++++ .../tensorflow/TensorflowGraphUnitTest.java | 21 ++++++++ 8 files changed, 158 insertions(+) create mode 100644 tensorflow-java/.gitignore create mode 100644 tensorflow-java/README.md create mode 100644 tensorflow-java/pom.xml create mode 100644 tensorflow-java/src/main/java/org/baeldung/tensorflow/TensorflowGraph.java create mode 100644 tensorflow-java/src/main/java/org/baeldung/tensorflow/TensorflowSavedModel.java create mode 100644 tensorflow-java/src/main/python/tensorflowGraph.py create mode 100644 tensorflow-java/src/test/java/org/baeldung/tensorflow/TensorflowGraphUnitTest.java diff --git a/pom.xml b/pom.xml index 18e3ace31b..826b8eea63 100644 --- a/pom.xml +++ b/pom.xml @@ -526,6 +526,9 @@ rxjava rxjava-2 software-security/sql-injection-samples + + tensorflow-java + @@ -742,6 +745,8 @@ xml xmlunit-2 xstream + + tensorflow-java diff --git a/tensorflow-java/.gitignore b/tensorflow-java/.gitignore new file mode 100644 index 0000000000..eaea64ae48 --- /dev/null +++ b/tensorflow-java/.gitignore @@ -0,0 +1,6 @@ +/.settings +/model +/target +.classpath +.project +.springBeans \ No newline at end of file diff --git a/tensorflow-java/README.md b/tensorflow-java/README.md new file mode 100644 index 0000000000..aac5b7544c --- /dev/null +++ b/tensorflow-java/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [TensorFlow for Java](https://www.baeldung.com/xxxx) diff --git a/tensorflow-java/pom.xml b/tensorflow-java/pom.xml new file mode 100644 index 0000000000..e9d92157e8 --- /dev/null +++ b/tensorflow-java/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + com.baeldung + tensorflow-java + 1.0-SNAPSHOT + jar + http://maven.apache.org + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + 1.8 + 1.12.0 + 5.4.0 + + + + + org.tensorflow + tensorflow + ${tensorflow.version} + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/tensorflow-java/src/main/java/org/baeldung/tensorflow/TensorflowGraph.java b/tensorflow-java/src/main/java/org/baeldung/tensorflow/TensorflowGraph.java new file mode 100644 index 0000000000..a44ef4c4ee --- /dev/null +++ b/tensorflow-java/src/main/java/org/baeldung/tensorflow/TensorflowGraph.java @@ -0,0 +1,41 @@ +package org.baeldung.tensorflow; + +import org.tensorflow.DataType; +import org.tensorflow.Graph; +import org.tensorflow.Operation; +import org.tensorflow.Session; +import org.tensorflow.Tensor; + +public class TensorflowGraph { + + public static Graph createGraph() { + Graph graph = new Graph(); + Operation a = graph.opBuilder("Const", "a").setAttr("dtype", DataType.fromClass(Double.class)) + .setAttr("value", Tensor.create(3.0, Double.class)).build(); + Operation b = graph.opBuilder("Const", "b").setAttr("dtype", DataType.fromClass(Double.class)) + .setAttr("value", Tensor.create(2.0, Double.class)).build(); + Operation x = graph.opBuilder("Placeholder", "x").setAttr("dtype", DataType.fromClass(Double.class)).build(); + Operation y = graph.opBuilder("Placeholder", "y").setAttr("dtype", DataType.fromClass(Double.class)).build(); + Operation ax = graph.opBuilder("Mul", "ax").addInput(a.output(0)).addInput(x.output(0)).build(); + Operation by = graph.opBuilder("Mul", "by").addInput(b.output(0)).addInput(y.output(0)).build(); + graph.opBuilder("Add", "z").addInput(ax.output(0)).addInput(by.output(0)).build(); + return graph; + } + + public static Object runGraph(Graph graph, Double x, Double y) { + Object result; + try (Session sess = new Session(graph)) { + result = sess.runner().fetch("z").feed("x", Tensor.create(x, Double.class)) + .feed("y", Tensor.create(y, Double.class)).run().get(0).expect(Double.class) + .doubleValue(); + } + return result; + } + + public static void main(String[] args) { + Graph graph = TensorflowGraph.createGraph(); + Object result = TensorflowGraph.runGraph(graph, 3.0, 6.0); + System.out.println(result); + graph.close(); + } +} \ No newline at end of file diff --git a/tensorflow-java/src/main/java/org/baeldung/tensorflow/TensorflowSavedModel.java b/tensorflow-java/src/main/java/org/baeldung/tensorflow/TensorflowSavedModel.java new file mode 100644 index 0000000000..4259a787e8 --- /dev/null +++ b/tensorflow-java/src/main/java/org/baeldung/tensorflow/TensorflowSavedModel.java @@ -0,0 +1,14 @@ +package org.baeldung.tensorflow; + +import org.tensorflow.SavedModelBundle; +import org.tensorflow.Tensor; + +public class TensorflowSavedModel { + + public static void main(String[] args) { + SavedModelBundle model = SavedModelBundle.load("./model", "serve"); + Tensor tensor = model.session().runner().fetch("z").feed("x", Tensor.create(3, Integer.class)) + .feed("y", Tensor.create(3, Integer.class)).run().get(0).expect(Integer.class); + System.out.println(tensor.intValue()); + } +} \ No newline at end of file diff --git a/tensorflow-java/src/main/python/tensorflowGraph.py b/tensorflow-java/src/main/python/tensorflowGraph.py new file mode 100644 index 0000000000..ab7f8810ac --- /dev/null +++ b/tensorflow-java/src/main/python/tensorflowGraph.py @@ -0,0 +1,16 @@ +import tensorflow as tf +graph = tf.Graph() +builder = tf.saved_model.builder.SavedModelBuilder('./model') +writer = tf.summary.FileWriter('.') +with graph.as_default(): + a = tf.constant(2, name='a') + b = tf.constant(3, name='b') + x = tf.placeholder(tf.int32, name='x') + y = tf.placeholder(tf.int32, name='y') + z = tf.math.add(a*x, b*y, name='z') + writer.add_graph(tf.get_default_graph()) + writer.flush() + sess = tf.Session() + sess.run(z, feed_dict = {x: 2, y: 3}) + builder.add_meta_graph_and_variables(sess, [tf.saved_model.tag_constants.SERVING]) + builder.save() diff --git a/tensorflow-java/src/test/java/org/baeldung/tensorflow/TensorflowGraphUnitTest.java b/tensorflow-java/src/test/java/org/baeldung/tensorflow/TensorflowGraphUnitTest.java new file mode 100644 index 0000000000..51df6a4322 --- /dev/null +++ b/tensorflow-java/src/test/java/org/baeldung/tensorflow/TensorflowGraphUnitTest.java @@ -0,0 +1,21 @@ +package org.baeldung.tensorflow; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Test; +import org.tensorflow.Graph; + +public class TensorflowGraphUnitTest { + + @Test + public void givenTensorflowGraphWhenRunInSessionReturnsExpectedResult() { + + Graph graph = TensorflowGraph.createGraph(); + Object result = TensorflowGraph.runGraph(graph, 3.0, 6.0); + assertEquals(21.0, result); + System.out.println(result); + graph.close(); + + } + +} From bac1103dccb43872ff84e7b3598bfc7916b927a9 Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Fri, 15 Mar 2019 14:38:26 +0000 Subject: [PATCH 363/496] BAEL-2522 - Reverting changes --- java-dates-2/.gitignore | 29 ---------- java-dates-2/pom.xml | 55 ------------------- ...XmlGregorianCalendarConverterUnitTest.java | 34 ------------ pom.xml | 1 - 4 files changed, 119 deletions(-) delete mode 100644 java-dates-2/.gitignore delete mode 100644 java-dates-2/pom.xml delete mode 100644 java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java diff --git a/java-dates-2/.gitignore b/java-dates-2/.gitignore deleted file mode 100644 index 6471aabbcf..0000000000 --- a/java-dates-2/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -*.class - -0.* - -#folders# -/target -/neoDb* -/data -/src/main/webapp/WEB-INF/classes -*/META-INF/* -.resourceCache - -# Packaged files # -*.jar -*.war -*.ear - -# Files generated by integration tests -*.txt -backup-pom.xml -/bin/ -/temp - -#IntelliJ specific -.idea/ -*.iml - -#jenv -.java-version \ No newline at end of file diff --git a/java-dates-2/pom.xml b/java-dates-2/pom.xml deleted file mode 100644 index 93216e3ffa..0000000000 --- a/java-dates-2/pom.xml +++ /dev/null @@ -1,55 +0,0 @@ - - 4.0.0 - com.baeldung - java-dates-2 - 0.1.0-SNAPSHOT - jar - java-dates-2 - - - com.baeldung - parent-java - 0.0.1-SNAPSHOT - ../parent-java - - - - - - org.assertj - assertj-core - ${assertj.version} - test - - - - - java-dates-2 - - - src/main/resources - true - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - - - - - - - - 3.6.1 - 1.9 - 1.9 - - diff --git a/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java b/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java deleted file mode 100644 index 34510a3167..0000000000 --- a/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.xmlgregoriancalendar; - -import org.junit.Test; - -import javax.xml.datatype.DatatypeConfigurationException; -import javax.xml.datatype.DatatypeFactory; -import javax.xml.datatype.XMLGregorianCalendar; -import java.time.LocalDate; - -import static org.assertj.core.api.Assertions.assertThat; - -public class XmlGregorianCalendarConverterUnitTest { - - @Test - public void fromLocalDateToXMLGregorianCalendar() throws DatatypeConfigurationException { - LocalDate localDate = LocalDate.of(2017, 4, 25); - XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(localDate.toString()); - - assertThat(xmlGregorianCalendar.getYear()).isEqualTo(localDate.getYear()); - assertThat(xmlGregorianCalendar.getMonth()).isEqualTo(localDate.getMonthValue()); - assertThat(xmlGregorianCalendar.getDay()).isEqualTo(localDate.getDayOfMonth()); - } - - @Test - public void fromXMLGregorianCalendarToLocalDate() throws DatatypeConfigurationException { - XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar("2017-04-25"); - LocalDate localDate = LocalDate.of(xmlGregorianCalendar.getYear(), xmlGregorianCalendar.getMonth(), xmlGregorianCalendar.getDay()); - - assertThat(localDate.getYear()).isEqualTo(xmlGregorianCalendar.getYear()); - assertThat(localDate.getMonthValue()).isEqualTo(xmlGregorianCalendar.getMonth()); - assertThat(localDate.getDayOfMonth()).isEqualTo(xmlGregorianCalendar.getDay()); - } - -} diff --git a/pom.xml b/pom.xml index ac1273b28d..58d57ade05 100644 --- a/pom.xml +++ b/pom.xml @@ -440,7 +440,6 @@ java-collections-conversions java-collections-maps - java-dates-2 java-lite java-numbers From 9b6a3a0f881e71df01327ef778d772df5ca5aa3e Mon Sep 17 00:00:00 2001 From: cdjole Date: Fri, 15 Mar 2019 17:56:19 +0100 Subject: [PATCH 364/496] New module core-java-jvm added (#6539) --- core-java-jvm/README.md | 6 +++ core-java-jvm/pom.xml | 40 +++++++++++++++++++ .../inlining/ConsecutiveNumbersSum.java | 0 .../baeldung/inlining/InliningExample.java | 0 .../ConsecutiveNumbersSumUnitTest.java | 0 pom.xml | 3 +- 6 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 core-java-jvm/README.md create mode 100644 core-java-jvm/pom.xml rename {core-java => core-java-jvm}/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java (100%) rename {core-java => core-java-jvm}/src/main/java/com/baeldung/inlining/InliningExample.java (100%) rename {core-java => core-java-jvm}/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java (100%) diff --git a/core-java-jvm/README.md b/core-java-jvm/README.md new file mode 100644 index 0000000000..529453f3c4 --- /dev/null +++ b/core-java-jvm/README.md @@ -0,0 +1,6 @@ +========= + +## Core Java JVM Cookbooks and Examples + +### Relevant Articles: +- [Method Inlining in the JVM](http://www.baeldung.com/method-inlining-in-the-jvm/) diff --git a/core-java-jvm/pom.xml b/core-java-jvm/pom.xml new file mode 100644 index 0000000000..752b26f03f --- /dev/null +++ b/core-java-jvm/pom.xml @@ -0,0 +1,40 @@ + + 4.0.0 + com.baeldung + core-java-jvm + 0.1.0-SNAPSHOT + jar + core-java-jvm + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + junit + junit + ${junit.version} + test + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + 3.5 + 3.6.1 + + diff --git a/core-java/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java b/core-java-jvm/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java similarity index 100% rename from core-java/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java rename to core-java-jvm/src/main/java/com/baeldung/inlining/ConsecutiveNumbersSum.java diff --git a/core-java/src/main/java/com/baeldung/inlining/InliningExample.java b/core-java-jvm/src/main/java/com/baeldung/inlining/InliningExample.java similarity index 100% rename from core-java/src/main/java/com/baeldung/inlining/InliningExample.java rename to core-java-jvm/src/main/java/com/baeldung/inlining/InliningExample.java diff --git a/core-java/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java b/core-java-jvm/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java similarity index 100% rename from core-java/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java rename to core-java-jvm/src/test/java/com/baeldung/inlining/ConsecutiveNumbersSumUnitTest.java diff --git a/pom.xml b/pom.xml index 826b8eea63..5858df01e1 100644 --- a/pom.xml +++ b/pom.xml @@ -393,7 +393,8 @@ core-java-networking core-java-perf core-java-sun - core-java + core-java + core-java-jvm core-scala couchbase custom-pmd From 2b28336cd6f7709d1751a2d5f1838017e69b8266 Mon Sep 17 00:00:00 2001 From: Andrey Shcherbakov Date: Fri, 15 Mar 2019 23:45:56 +0100 Subject: [PATCH 365/496] Add the code for article "Kotlin Annotations" (BAEL-2579) (#6540) --- .../com/baeldung/annotations/Annotations.kt | 7 ++++ .../kotlin/com/baeldung/annotations/Item.kt | 3 ++ .../kotlin/com/baeldung/annotations/Main.kt | 7 ++++ .../com/baeldung/annotations/Validator.kt | 38 +++++++++++++++++ .../annotations/ValidationUnitTest.kt | 42 +++++++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Annotations.kt create mode 100644 core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Item.kt create mode 100644 core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Main.kt create mode 100644 core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Validator.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationUnitTest.kt diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Annotations.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Annotations.kt new file mode 100644 index 0000000000..a8f83446dc --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Annotations.kt @@ -0,0 +1,7 @@ +package com.baeldung.annotations + +@Target(AnnotationTarget.FIELD) +annotation class Positive + +@Target(AnnotationTarget.FIELD) +annotation class AllowedNames(val names: Array) diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Item.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Item.kt new file mode 100644 index 0000000000..6864fe416e --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Item.kt @@ -0,0 +1,3 @@ +package com.baeldung.annotations + +class Item(@Positive val amount: Float, @AllowedNames(["Alice", "Bob"]) val name: String) \ No newline at end of file diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Main.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Main.kt new file mode 100644 index 0000000000..2b7f2c5590 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Main.kt @@ -0,0 +1,7 @@ +package com.baeldung.annotations + +fun main(args: Array) { + val item = Item(amount = 1.0f, name = "Bob") + val validator = Validator() + println("Is instance valid? ${validator.isValid(item)}") +} diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Validator.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Validator.kt new file mode 100644 index 0000000000..40139048ab --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/annotations/Validator.kt @@ -0,0 +1,38 @@ +package com.baeldung.annotations + +/** + * Naive annotation-based validator. + * @author A.Shcherbakov + */ +class Validator() { + + /** + * Return true if every item's property annotated with @Positive is positive and if + * every item's property annotated with @AllowedNames has a value specified in that annotation. + */ + fun isValid(item: Item): Boolean { + val fields = item::class.java.declaredFields + for (field in fields) { + field.isAccessible = true + for (annotation in field.annotations) { + val value = field.get(item) + if (field.isAnnotationPresent(Positive::class.java)) { + val amount = value as Float + if (amount < 0) { + return false + } + } + if (field.isAnnotationPresent(AllowedNames::class.java)) { + val allowedNames = field.getAnnotation(AllowedNames::class.java)?.names + val name = value as String + allowedNames?.let { + if (!it.contains(name)) { + return false + } + } + } + } + } + return true + } +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationUnitTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationUnitTest.kt new file mode 100644 index 0000000000..506b7a24b5 --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationUnitTest.kt @@ -0,0 +1,42 @@ +package com.baeldung.annotations + +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Test + + +class ValidationUnitTest { + + @Test + fun whenAmountIsOneAndNameIsAlice_thenTrue() { + assertTrue(Validator().isValid(Item(1f, "Alice"))) + } + + @Test + fun whenAmountIsOneAndNameIsBob_thenTrue() { + assertTrue(Validator().isValid(Item(1f, "Bob"))) + } + + + @Test + fun whenAmountIsMinusOneAndNameIsAlice_thenFalse() { + assertFalse(Validator().isValid(Item(-1f, "Alice"))) + } + + @Test + fun whenAmountIsMinusOneAndNameIsBob_thenFalse() { + assertFalse(Validator().isValid(Item(-1f, "Bob"))) + } + + @Test + fun whenAmountIsOneAndNameIsTom_thenFalse() { + assertFalse(Validator().isValid(Item(1f, "Tom"))) + } + + @Test + fun whenAmountIsMinusOneAndNameIsTom_thenFalse() { + assertFalse(Validator().isValid(Item(-1f, "Tom"))) + } + + +} \ No newline at end of file From 7b5d3a20e19d9f9b046a3d4acadf7bb2553ecbde Mon Sep 17 00:00:00 2001 From: "anilkivilcim.eray" Date: Sat, 16 Mar 2019 10:43:29 +0300 Subject: [PATCH 366/496] BAEL-2762 init --- spring-boot-security/pom.xml | 17 +++++++++++++++-- .../WebSecurityConfigurer.java | 2 +- .../SpringBootSecurityApplication.java | 3 ++- .../SpringBootOAuth2SsoApplication.java | 1 + .../main/resources/application-authz.properties | 2 +- .../resources/application-taglibs.properties | 4 ++-- .../BasicAuthConfigurationIntegrationTest.java | 3 +-- 7 files changed, 23 insertions(+), 9 deletions(-) diff --git a/spring-boot-security/pom.xml b/spring-boot-security/pom.xml index aaa0fbf4c7..73d08c4485 100644 --- a/spring-boot-security/pom.xml +++ b/spring-boot-security/pom.xml @@ -8,10 +8,10 @@ jar - parent-boot-1 + parent-boot-2 com.baeldung 0.0.1-SNAPSHOT - ../parent-boot-1 + ../parent-boot-2 @@ -22,6 +22,7 @@ org.springframework.security.oauth spring-security-oauth2 + ${spring-security-oauth2.version} org.springframework.boot @@ -55,6 +56,17 @@ spring-security-test test + + org.springframework.boot + spring-boot-autoconfigure + 2.1.1.RELEASE + + + org.springframework.security.oauth.boot + spring-security-oauth2-autoconfigure + 2.1.0.RELEASE + + @@ -68,6 +80,7 @@ com.baeldung.springbootsecurity.basic_auth.SpringBootSecurityApplication + 2.2.1.RELEASE diff --git a/spring-boot-security/src/main/java/com/baeldung/integrationtesting/WebSecurityConfigurer.java b/spring-boot-security/src/main/java/com/baeldung/integrationtesting/WebSecurityConfigurer.java index 32a48ce612..16ce8e6fc6 100644 --- a/spring-boot-security/src/main/java/com/baeldung/integrationtesting/WebSecurityConfigurer.java +++ b/spring-boot-security/src/main/java/com/baeldung/integrationtesting/WebSecurityConfigurer.java @@ -12,7 +12,7 @@ public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter { protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("spring") - .password("secret") + .password("{noop}secret") .roles("USER"); } diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java index 2ecad4ae35..7da9fbad06 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/SpringBootSecurityApplication.java @@ -2,7 +2,8 @@ package com.baeldung.springbootsecurity.basic_auth; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; + @SpringBootApplication(exclude = { SecurityAutoConfiguration.class diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2sso/SpringBootOAuth2SsoApplication.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2sso/SpringBootOAuth2SsoApplication.java index b1cd580f08..342c246e66 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2sso/SpringBootOAuth2SsoApplication.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2sso/SpringBootOAuth2SsoApplication.java @@ -1,6 +1,7 @@ package com.baeldung.springbootsecurity.oauth2sso; import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; import org.springframework.boot.builder.SpringApplicationBuilder; diff --git a/spring-boot-security/src/main/resources/application-authz.properties b/spring-boot-security/src/main/resources/application-authz.properties index d29b0cdd3c..0c53999bb3 100644 --- a/spring-boot-security/src/main/resources/application-authz.properties +++ b/spring-boot-security/src/main/resources/application-authz.properties @@ -1,3 +1,3 @@ -security.user.password=password +spring.security.user.password=password security.oauth2.client.client-id=client security.oauth2.client.client-secret=secret diff --git a/spring-boot-security/src/main/resources/application-taglibs.properties b/spring-boot-security/src/main/resources/application-taglibs.properties index 218868405f..3e482ed92a 100644 --- a/spring-boot-security/src/main/resources/application-taglibs.properties +++ b/spring-boot-security/src/main/resources/application-taglibs.properties @@ -1,3 +1,3 @@ #jsp config -spring.mvc.view.prefix: /WEB-INF/views/ -spring.mvc.view.suffix: .jsp +spring.mvc.view.prefix= /WEB-INF/views/ +spring.mvc.view.suffix= .jsp diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java index 32c3fbdef4..98e76e7bab 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java @@ -1,10 +1,9 @@ package com.baeldung.springbootsecurity.basic_auth; -import com.baeldung.springbootsecurity.basic_auth.SpringBootSecurityApplication; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.http.HttpStatus; From 4ef58c00667058c2cd6ebd7d64285b4e0ee5d84a Mon Sep 17 00:00:00 2001 From: Dhananjay Singh Date: Sat, 16 Mar 2019 12:45:16 +0100 Subject: [PATCH 367/496] Modified tests --- .../controller/AppControllerIntegrationTest.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java index 9ad940683f..a55c0a69e4 100644 --- a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java @@ -60,7 +60,7 @@ public class AppControllerIntegrationTest { .statusCode(HttpStatus.OK.value()) .body("id", equalTo(testMovie.getId())) .body("name", equalTo(testMovie.getName())) - .body("synopsis", equalTo(testMovie.getSynopsis())); + .body("synopsis", notNullValue()); Movie result = get(uri + "/movie/" + testMovie.getId()).then() .assertThat() @@ -68,6 +68,13 @@ public class AppControllerIntegrationTest { .extract() .as(Movie.class); assertThat(result).isEqualTo(testMovie); + + String responseString = get(uri + "/movie/" + testMovie.getId()).then() + .assertThat() + .statusCode(HttpStatus.OK.value()) + .extract() + .asString(); + assertThat(responseString).isNotEmpty(); } @Test From 4d05dd1d9e7a72bf2903286725463d0b04e8d678 Mon Sep 17 00:00:00 2001 From: isaolmez Date: Sat, 16 Mar 2019 17:01:42 +0300 Subject: [PATCH 368/496] BAEL-2715: Modified customizers --- ...tyWebServerFactoryBootstrapCustomizer.java | 49 +++++++++++++++++++ .../NettyWebServerFactoryPortCustomizer.java | 30 ------------ .../NettyWebServerFactorySslCustomizer.java | 6 ++- 3 files changed, 54 insertions(+), 31 deletions(-) create mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryBootstrapCustomizer.java delete mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryBootstrapCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryBootstrapCustomizer.java new file mode 100644 index 0000000000..05b2fbb7f7 --- /dev/null +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryBootstrapCustomizer.java @@ -0,0 +1,49 @@ +package com.baeldung.serverconfig.server; + +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.stereotype.Component; +import reactor.netty.http.server.HttpServer; + +@Component +public class NettyWebServerFactoryBootstrapCustomizer implements WebServerFactoryCustomizer { + + @Override + public void customize(NettyReactiveWebServerFactory serverFactory) { + serverFactory.addServerCustomizers(new PortCustomizer(8443)); + serverFactory.addServerCustomizers(new EventLoopNettyCustomizer()); + } + + private static class PortCustomizer implements NettyServerCustomizer { + + private final int port; + + private PortCustomizer(int port) { + this.port = port; + } + + @Override + public HttpServer apply(HttpServer httpServer) { + return httpServer.port(port); + } + } + + private static class EventLoopNettyCustomizer implements NettyServerCustomizer { + + @Override + public HttpServer apply(HttpServer httpServer) { + EventLoopGroup parentGroup = new NioEventLoopGroup(); + EventLoopGroup childGroup = new NioEventLoopGroup(); + return httpServer + .tcpConfiguration(tcpServer -> tcpServer.bootstrap( + serverBootstrap -> serverBootstrap.group(parentGroup, childGroup).channel(NioServerSocketChannel.class) + )); + + } + + } +} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java deleted file mode 100644 index 1dda58baa4..0000000000 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryPortCustomizer.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.serverconfig.server; - -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; -import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.stereotype.Component; -import reactor.netty.http.server.HttpServer; - -@Component -public class NettyWebServerFactoryPortCustomizer implements WebServerFactoryCustomizer { - - @Override - public void customize(NettyReactiveWebServerFactory serverFactory) { - serverFactory.addServerCustomizers(new PortCustomizer(8443)); - } - - private static class PortCustomizer implements NettyServerCustomizer { - - private final int port; - - private PortCustomizer(int port) { - this.port = port; - } - - @Override - public HttpServer apply(HttpServer httpServer) { - return httpServer.port(port); - } - } -} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java index 0aceae39dc..d03c3a7f40 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java @@ -1,6 +1,8 @@ package com.baeldung.serverconfig.server; import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.embedded.netty.SslServerCustomizer; +import org.springframework.boot.web.server.Http2; import org.springframework.boot.web.server.Ssl; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.stereotype.Component; @@ -16,7 +18,9 @@ public class NettyWebServerFactorySslCustomizer implements WebServerFactoryCusto ssl.setKeyAlias("alias"); ssl.setKeyPassword("password"); ssl.setKeyStorePassword("secret"); - serverFactory.setSsl(ssl); + Http2 http2 = new Http2(); + http2.setEnabled(false); + serverFactory.addServerCustomizers(new SslServerCustomizer(ssl, http2, null)); serverFactory.setPort(8443); } } From 6ad4766776065f629a3f05ccc75fee8bc60e0422 Mon Sep 17 00:00:00 2001 From: Andrey Shcherbakov Date: Sat, 16 Mar 2019 15:50:04 +0100 Subject: [PATCH 369/496] Adjust the unit test (#6543) * Add the code for article "Kotlin Annotations" (BAEL-2579) * Adjust the Validation test --- .../baeldung/annotations/ValidationTest.kt | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt new file mode 100644 index 0000000000..97fb3434ee --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt @@ -0,0 +1,41 @@ +package com.baeldung.annotations + +import org.junit.Test +import kotlin.test.assertTrue +import kotlin.test.assertFalse + +class ValidationUnitTest { + + @Test + fun whenAmountIsOneAndNameIsAlice_thenTrue() { + assertTrue(Validator().isValid(Item(1f, "Alice"))) + } + + @Test + fun whenAmountIsOneAndNameIsBob_thenTrue() { + assertTrue(Validator().isValid(Item(1f, "Bob"))) + } + + + @Test + fun whenAmountIsMinusOneAndNameIsAlice_thenFalse() { + assertFalse(Validator().isValid(Item(-1f, "Alice"))) + } + + @Test + fun whenAmountIsMinusOneAndNameIsBob_thenFalse() { + assertFalse(Validator().isValid(Item(-1f, "Bob"))) + } + + @Test + fun whenAmountIsOneAndNameIsTom_thenFalse() { + assertFalse(Validator().isValid(Item(1f, "Tom"))) + } + + @Test + fun whenAmountIsMinusOneAndNameIsTom_thenFalse() { + assertFalse(Validator().isValid(Item(-1f, "Tom"))) + } + + +} \ No newline at end of file From 70736ee16ad3b7a58b015836b8d2e6ee1548f362 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 17 Mar 2019 00:28:43 +0530 Subject: [PATCH 370/496] [BAEL-10982] - Fixed application startup --- spring-resttemplate/pom.xml | 4 ++++ .../RestTemplateConfigurationApplication.java | 2 +- .../baeldung/resttemplate/configuration/SpringConfig.java | 5 +++++ .../java/org/baeldung/{ => resttemplate}/web/dto/Foo.java | 2 +- .../{ => resttemplate}/web/exception/NotFoundException.java | 2 +- .../web/handler/RestTemplateResponseErrorHandler.java | 4 ++-- .../java/org/baeldung/{ => resttemplate}/web/model/Bar.java | 2 +- .../org/baeldung/{ => resttemplate}/web/model/Employee.java | 2 +- .../{ => resttemplate}/web/service/BarConsumerService.java | 6 +++--- .../{ => resttemplate}/web/service/EmployeeService.java | 4 ++-- .../java/org/baeldung/SpringContextIntegrationTest.java | 2 +- .../java/org/baeldung/client/RestTemplateBasicLiveTest.java | 2 +- .../RestTemplateResponseErrorHandlerIntegrationTest.java | 5 +++-- .../EmployeeServiceMockRestServiceServerUnitTest.java | 3 ++- .../org/baeldung/web/service/EmployeeServiceUnitTest.java | 3 ++- 15 files changed, 30 insertions(+), 18 deletions(-) rename spring-resttemplate/src/main/java/org/baeldung/resttemplate/{configuration => }/RestTemplateConfigurationApplication.java (89%) rename spring-resttemplate/src/main/java/org/baeldung/{ => resttemplate}/web/dto/Foo.java (93%) rename spring-resttemplate/src/main/java/org/baeldung/{ => resttemplate}/web/exception/NotFoundException.java (55%) rename spring-resttemplate/src/main/java/org/baeldung/{ => resttemplate}/web/handler/RestTemplateResponseErrorHandler.java (91%) rename spring-resttemplate/src/main/java/org/baeldung/{ => resttemplate}/web/model/Bar.java (87%) rename spring-resttemplate/src/main/java/org/baeldung/{ => resttemplate}/web/model/Employee.java (95%) rename spring-resttemplate/src/main/java/org/baeldung/{ => resttemplate}/web/service/BarConsumerService.java (78%) rename spring-resttemplate/src/main/java/org/baeldung/{ => resttemplate}/web/service/EmployeeService.java (89%) diff --git a/spring-resttemplate/pom.xml b/spring-resttemplate/pom.xml index 9a0978f120..06d4eed9fc 100644 --- a/spring-resttemplate/pom.xml +++ b/spring-resttemplate/pom.xml @@ -25,6 +25,10 @@ org.springframework.boot spring-boot-devtools + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-test diff --git a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/RestTemplateConfigurationApplication.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/RestTemplateConfigurationApplication.java similarity index 89% rename from spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/RestTemplateConfigurationApplication.java rename to spring-resttemplate/src/main/java/org/baeldung/resttemplate/RestTemplateConfigurationApplication.java index 76fc346aca..9a361e92c9 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/RestTemplateConfigurationApplication.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/RestTemplateConfigurationApplication.java @@ -1,4 +1,4 @@ -package org.baeldung.resttemplate.configuration; +package org.baeldung.resttemplate; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; diff --git a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/SpringConfig.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/SpringConfig.java index 4e121185b1..966d5bcaa1 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/SpringConfig.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/SpringConfig.java @@ -7,6 +7,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; +import org.springframework.web.client.RestTemplate; @Configuration @EnableAutoConfiguration @@ -25,4 +26,8 @@ public class SpringConfig { return new RestTemplateBuilder(customRestTemplateCustomizer()); } + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } } diff --git a/spring-resttemplate/src/main/java/org/baeldung/web/dto/Foo.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/dto/Foo.java similarity index 93% rename from spring-resttemplate/src/main/java/org/baeldung/web/dto/Foo.java rename to spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/dto/Foo.java index 240b368b50..ed0a42c429 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/web/dto/Foo.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/dto/Foo.java @@ -1,4 +1,4 @@ -package org.baeldung.web.dto; +package org.baeldung.resttemplate.web.dto; import com.thoughtworks.xstream.annotations.XStreamAlias; diff --git a/spring-resttemplate/src/main/java/org/baeldung/web/exception/NotFoundException.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/exception/NotFoundException.java similarity index 55% rename from spring-resttemplate/src/main/java/org/baeldung/web/exception/NotFoundException.java rename to spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/exception/NotFoundException.java index 5b4d80a659..3e606e9314 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/web/exception/NotFoundException.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/exception/NotFoundException.java @@ -1,4 +1,4 @@ -package org.baeldung.web.exception; +package org.baeldung.resttemplate.web.exception; public class NotFoundException extends RuntimeException { } diff --git a/spring-resttemplate/src/main/java/org/baeldung/web/handler/RestTemplateResponseErrorHandler.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java similarity index 91% rename from spring-resttemplate/src/main/java/org/baeldung/web/handler/RestTemplateResponseErrorHandler.java rename to spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java index b1b87e89a5..d65e837067 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/web/handler/RestTemplateResponseErrorHandler.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java @@ -1,6 +1,6 @@ -package org.baeldung.web.handler; +package org.baeldung.resttemplate.web.handler; -import org.baeldung.web.exception.NotFoundException; +import org.baeldung.resttemplate.web.exception.NotFoundException; import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Component; diff --git a/spring-resttemplate/src/main/java/org/baeldung/web/model/Bar.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/model/Bar.java similarity index 87% rename from spring-resttemplate/src/main/java/org/baeldung/web/model/Bar.java rename to spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/model/Bar.java index 474e2070a5..cf5279697f 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/web/model/Bar.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/model/Bar.java @@ -1,4 +1,4 @@ -package org.baeldung.web.model; +package org.baeldung.resttemplate.web.model; public class Bar { private String id; diff --git a/spring-resttemplate/src/main/java/org/baeldung/web/model/Employee.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/model/Employee.java similarity index 95% rename from spring-resttemplate/src/main/java/org/baeldung/web/model/Employee.java rename to spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/model/Employee.java index 7cab4a0430..a9b84a77b4 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/web/model/Employee.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/model/Employee.java @@ -1,4 +1,4 @@ -package org.baeldung.web.model; +package org.baeldung.resttemplate.web.model; import java.util.Date; import java.util.Objects; diff --git a/spring-resttemplate/src/main/java/org/baeldung/web/service/BarConsumerService.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/BarConsumerService.java similarity index 78% rename from spring-resttemplate/src/main/java/org/baeldung/web/service/BarConsumerService.java rename to spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/BarConsumerService.java index 0bf24bd480..54a66ea591 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/web/service/BarConsumerService.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/BarConsumerService.java @@ -1,7 +1,7 @@ -package org.baeldung.web.service; +package org.baeldung.resttemplate.web.service; -import org.baeldung.web.handler.RestTemplateResponseErrorHandler; -import org.baeldung.web.model.Bar; +import org.baeldung.resttemplate.web.handler.RestTemplateResponseErrorHandler; +import org.baeldung.resttemplate.web.model.Bar; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.stereotype.Service; diff --git a/spring-resttemplate/src/main/java/org/baeldung/web/service/EmployeeService.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/EmployeeService.java similarity index 89% rename from spring-resttemplate/src/main/java/org/baeldung/web/service/EmployeeService.java rename to spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/EmployeeService.java index 91614e90ad..c6562fbc94 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/web/service/EmployeeService.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/EmployeeService.java @@ -1,6 +1,6 @@ -package org.baeldung.web.service; +package org.baeldung.resttemplate.web.service; -import org.baeldung.web.model.Employee; +import org.baeldung.resttemplate.web.model.Employee; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-resttemplate/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-resttemplate/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 3a5a20cfeb..3c762b894b 100644 --- a/spring-resttemplate/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-resttemplate/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -1,6 +1,6 @@ package org.baeldung; -import org.baeldung.resttemplate.configuration.RestTemplateConfigurationApplication; +import org.baeldung.resttemplate.RestTemplateConfigurationApplication; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; diff --git a/spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java b/spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java index 143aa079d5..c837e23547 100644 --- a/spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java +++ b/spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java @@ -14,7 +14,7 @@ import java.net.URI; import java.util.Arrays; import java.util.Set; -import org.baeldung.web.dto.Foo; +import org.baeldung.resttemplate.web.dto.Foo; import org.junit.Before; import org.junit.Test; import org.springframework.http.HttpEntity; diff --git a/spring-resttemplate/src/test/java/org/baeldung/web/handler/RestTemplateResponseErrorHandlerIntegrationTest.java b/spring-resttemplate/src/test/java/org/baeldung/web/handler/RestTemplateResponseErrorHandlerIntegrationTest.java index 2dfa81f441..60069cea71 100644 --- a/spring-resttemplate/src/test/java/org/baeldung/web/handler/RestTemplateResponseErrorHandlerIntegrationTest.java +++ b/spring-resttemplate/src/test/java/org/baeldung/web/handler/RestTemplateResponseErrorHandlerIntegrationTest.java @@ -1,7 +1,8 @@ package org.baeldung.web.handler; -import org.baeldung.web.exception.NotFoundException; -import org.baeldung.web.model.Bar; +import org.baeldung.resttemplate.web.exception.NotFoundException; +import org.baeldung.resttemplate.web.handler.RestTemplateResponseErrorHandler; +import org.baeldung.resttemplate.web.model.Bar; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-resttemplate/src/test/java/org/baeldung/web/service/EmployeeServiceMockRestServiceServerUnitTest.java b/spring-resttemplate/src/test/java/org/baeldung/web/service/EmployeeServiceMockRestServiceServerUnitTest.java index a45af318f1..f93ba71666 100644 --- a/spring-resttemplate/src/test/java/org/baeldung/web/service/EmployeeServiceMockRestServiceServerUnitTest.java +++ b/spring-resttemplate/src/test/java/org/baeldung/web/service/EmployeeServiceMockRestServiceServerUnitTest.java @@ -7,7 +7,8 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat import java.net.URI; import org.baeldung.SpringTestConfig; -import org.baeldung.web.model.Employee; +import org.baeldung.resttemplate.web.model.Employee; +import org.baeldung.resttemplate.web.service.EmployeeService; import org.junit.Assert; import org.junit.Before; import org.junit.Test; diff --git a/spring-resttemplate/src/test/java/org/baeldung/web/service/EmployeeServiceUnitTest.java b/spring-resttemplate/src/test/java/org/baeldung/web/service/EmployeeServiceUnitTest.java index 23cd9a8fd2..f4b391573a 100644 --- a/spring-resttemplate/src/test/java/org/baeldung/web/service/EmployeeServiceUnitTest.java +++ b/spring-resttemplate/src/test/java/org/baeldung/web/service/EmployeeServiceUnitTest.java @@ -1,6 +1,7 @@ package org.baeldung.web.service; -import org.baeldung.web.model.Employee; +import org.baeldung.resttemplate.web.model.Employee; +import org.baeldung.resttemplate.web.service.EmployeeService; import org.junit.Assert; import org.junit.Before; import org.junit.Test; From d5e91a8d341ee6e937061c20db9e17d0b8594a8c Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Sat, 16 Mar 2019 22:15:22 +0000 Subject: [PATCH 371/496] Revert "BAEL-2522 - Reverting changes" This reverts commit bac1103dccb43872ff84e7b3598bfc7916b927a9. --- java-dates-2/.gitignore | 29 ++++++++++ java-dates-2/pom.xml | 55 +++++++++++++++++++ ...XmlGregorianCalendarConverterUnitTest.java | 34 ++++++++++++ pom.xml | 1 + 4 files changed, 119 insertions(+) create mode 100644 java-dates-2/.gitignore create mode 100644 java-dates-2/pom.xml create mode 100644 java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java diff --git a/java-dates-2/.gitignore b/java-dates-2/.gitignore new file mode 100644 index 0000000000..6471aabbcf --- /dev/null +++ b/java-dates-2/.gitignore @@ -0,0 +1,29 @@ +*.class + +0.* + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* +.resourceCache + +# Packaged files # +*.jar +*.war +*.ear + +# Files generated by integration tests +*.txt +backup-pom.xml +/bin/ +/temp + +#IntelliJ specific +.idea/ +*.iml + +#jenv +.java-version \ No newline at end of file diff --git a/java-dates-2/pom.xml b/java-dates-2/pom.xml new file mode 100644 index 0000000000..93216e3ffa --- /dev/null +++ b/java-dates-2/pom.xml @@ -0,0 +1,55 @@ + + 4.0.0 + com.baeldung + java-dates-2 + 0.1.0-SNAPSHOT + jar + java-dates-2 + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + java-dates-2 + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + + 3.6.1 + 1.9 + 1.9 + + diff --git a/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java b/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java new file mode 100644 index 0000000000..34510a3167 --- /dev/null +++ b/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java @@ -0,0 +1,34 @@ +package com.baeldung.xmlgregoriancalendar; + +import org.junit.Test; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThat; + +public class XmlGregorianCalendarConverterUnitTest { + + @Test + public void fromLocalDateToXMLGregorianCalendar() throws DatatypeConfigurationException { + LocalDate localDate = LocalDate.of(2017, 4, 25); + XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(localDate.toString()); + + assertThat(xmlGregorianCalendar.getYear()).isEqualTo(localDate.getYear()); + assertThat(xmlGregorianCalendar.getMonth()).isEqualTo(localDate.getMonthValue()); + assertThat(xmlGregorianCalendar.getDay()).isEqualTo(localDate.getDayOfMonth()); + } + + @Test + public void fromXMLGregorianCalendarToLocalDate() throws DatatypeConfigurationException { + XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar("2017-04-25"); + LocalDate localDate = LocalDate.of(xmlGregorianCalendar.getYear(), xmlGregorianCalendar.getMonth(), xmlGregorianCalendar.getDay()); + + assertThat(localDate.getYear()).isEqualTo(xmlGregorianCalendar.getYear()); + assertThat(localDate.getMonthValue()).isEqualTo(xmlGregorianCalendar.getMonth()); + assertThat(localDate.getDayOfMonth()).isEqualTo(xmlGregorianCalendar.getDay()); + } + +} diff --git a/pom.xml b/pom.xml index 58d57ade05..ac1273b28d 100644 --- a/pom.xml +++ b/pom.xml @@ -440,6 +440,7 @@ java-collections-conversions java-collections-maps + java-dates-2 java-lite java-numbers From 227ad26d0bd09869f76c631a02b90e3056987f04 Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Sat, 16 Mar 2019 22:16:48 +0000 Subject: [PATCH 372/496] BAEL-2522 - Commenting module --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ac1273b28d..d6a43db409 100644 --- a/pom.xml +++ b/pom.xml @@ -440,7 +440,7 @@ java-collections-conversions java-collections-maps - java-dates-2 + java-lite java-numbers From b7c109246031cad59efce302ac4e0b650ac865c0 Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Sat, 16 Mar 2019 17:56:54 -0500 Subject: [PATCH 373/496] BAEL-2711: Add spring-boot-angular module to pom.xml (#6492) * BAEL-2246: add link back to article * BAEL-2174: rename core-java-net module to core-java-networking * BAEL-2174: add link back to article * BAEL-2363 BAEL-2337 BAEL-1996 BAEL-2277 add links back to articles * BAEL-2367: add link back to article * BAEL-2335: add link back to article * BAEL-2413: add link back to article * Update README.MD * BAEL-2577: add link back to article * BAEL-2490: add link back to article * BAEL-2471: add link back to article * BAEL-2583: add link back to article * BAEL-2738: add link back to article * BAEL-2711: Add spring-boot-angular module to root pom * BAEL-2544 BAEL-2711 BAEL-2575 BAEL-2657 Add links back to articles --- core-kotlin-2/README.md | 2 ++ java-streams-2/README.md | 3 +++ persistence-modules/spring-boot-persistence/README.MD | 1 + spring-boot-angular/README.md | 3 +++ 4 files changed, 9 insertions(+) create mode 100644 java-streams-2/README.md create mode 100644 spring-boot-angular/README.md diff --git a/core-kotlin-2/README.md b/core-kotlin-2/README.md index 8d22c4f1a8..da2f7548d9 100644 --- a/core-kotlin-2/README.md +++ b/core-kotlin-2/README.md @@ -2,3 +2,5 @@ - [Void Type in Kotlin](https://www.baeldung.com/kotlin-void-type) - [How to use Kotlin Range Expressions](https://www.baeldung.com/kotlin-ranges) +- [Split a List into Parts in Kotlin](https://www.baeldung.com/kotlin-split-list-into-parts) + diff --git a/java-streams-2/README.md b/java-streams-2/README.md new file mode 100644 index 0000000000..83ef97686f --- /dev/null +++ b/java-streams-2/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: +- [Guide to Stream.reduce()](https://www.baeldung.com/java-stream-reduce) + diff --git a/persistence-modules/spring-boot-persistence/README.MD b/persistence-modules/spring-boot-persistence/README.MD index f62ca57a19..ee7c2e298e 100644 --- a/persistence-modules/spring-boot-persistence/README.MD +++ b/persistence-modules/spring-boot-persistence/README.MD @@ -7,3 +7,4 @@ - [Hibernate Field Naming with Spring Boot](https://www.baeldung.com/hibernate-field-naming-spring-boot) - [Integrating Spring Boot with HSQLDB](https://www.baeldung.com/spring-boot-hsqldb) - [Configuring a DataSource Programmatically in Spring Boot](https://www.baeldung.com/spring-boot-configure-data-source-programmatic) +- [Resolving “Failed to Configure a DataSource” Error](https://www.baeldung.com/spring-boot-failed-to-configure-data-source) diff --git a/spring-boot-angular/README.md b/spring-boot-angular/README.md new file mode 100644 index 0000000000..cfc1ea69f4 --- /dev/null +++ b/spring-boot-angular/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: +- [Building a Web Application with Spring Boot and Angular](https://www.baeldung.com/spring-boot-angular-web) + From f62a8d0f70bd1a1b21a3fbb350b78a91db7a5b7a Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 17 Mar 2019 12:26:00 +0200 Subject: [PATCH 374/496] small fixes to match articles --- .../baeldung/SpringBootRestApplication.java | 2 ++ .../com/baeldung/persistence/IOperations.java | 2 +- .../service/common/AbstractService.java | 5 ++-- .../java/com/baeldung/spring/WebConfig.java | 2 +- .../web/controller/FooController.java | 30 ++++++++++++++----- .../web/controller/RootController.java | 16 ++++------ ...sultsRetrievedDiscoverabilityListener.java | 2 +- .../src/main/resources/application.properties | 5 ++-- .../src/test/java/com/baeldung/Consts.java | 2 +- .../baeldung/common/web/AbstractLiveTest.java | 2 +- .../web/FooControllerAppIntegrationTest.java | 2 +- ...ooControllerCustomEtagIntegrationTest.java | 2 +- .../FooControllerWebLayerIntegrationTest.java | 2 +- .../com/baeldung/web/FooPageableLiveTest.java | 2 +- .../foo_API_test.postman_collection.json | 20 +++++-------- 15 files changed, 51 insertions(+), 45 deletions(-) diff --git a/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java index 62aae7619d..496f6acdfa 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java +++ b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java @@ -1,11 +1,13 @@ package com.baeldung; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootRestApplication { + public static void main(String[] args) { SpringApplication.run(SpringBootRestApplication.class, args); } diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java index 1cc732ab08..fbbba23013 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/IOperations.java @@ -9,7 +9,7 @@ public interface IOperations { // read - one - T findOne(final long id); + T findById(final long id); // read - all diff --git a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java index 5900c443b8..f589eaecf5 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java +++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/service/common/AbstractService.java @@ -18,9 +18,8 @@ public abstract class AbstractService implements IOperat @Override @Transactional(readOnly = true) - public T findOne(final long id) { - return getDao().findById(id) - .get(); + public T findById(final long id) { + return getDao().findById(id).orElse(null); } // read - all diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java index 4b876a8338..ab16b61e1d 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java +++ b/spring-boot-rest/src/main/java/com/baeldung/spring/WebConfig.java @@ -55,7 +55,7 @@ public class WebConfig implements WebMvcConfigurer { @Bean public FilterRegistrationBean shallowEtagHeaderFilter() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>( new ShallowEtagHeaderFilter()); - filterRegistrationBean.addUrlPatterns("/auth/foos/*"); + filterRegistrationBean.addUrlPatterns("/foos/*"); filterRegistrationBean.setName("etagFilter"); return filterRegistrationBean; } diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java index 255fcaabb7..0162d561b4 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java @@ -5,6 +5,7 @@ import java.util.List; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -20,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; import org.springframework.web.util.UriComponentsBuilder; import com.baeldung.persistence.model.Foo; @@ -32,7 +34,7 @@ import com.baeldung.web.util.RestPreconditions; import com.google.common.base.Preconditions; @RestController -@RequestMapping(value = "/auth/foos") +@RequestMapping(value = "/foos") public class FooController { @Autowired @@ -40,6 +42,10 @@ public class FooController { @Autowired private IFooService service; + + + @Value("${version}") + Integer version; public FooController() { super(); @@ -51,28 +57,36 @@ public class FooController { @GetMapping(value = "/{id}/custom-etag") public ResponseEntity findByIdWithCustomEtag(@PathVariable("id") final Long id, final HttpServletResponse response) { - final Foo resourceById = RestPreconditions.checkFound(service.findOne(id)); + final Foo foo = RestPreconditions.checkFound(service.findById(id)); eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response)); return ResponseEntity.ok() - .eTag(Long.toString(resourceById.getVersion())) - .body(resourceById); + .eTag(Long.toString(foo.getVersion())) + .body(foo); } // read - one @GetMapping(value = "/{id}") public Foo findById(@PathVariable("id") final Long id, final HttpServletResponse response) { - final Foo resourceById = RestPreconditions.checkFound(service.findOne(id)); + try { + final Foo resourceById = RestPreconditions.checkFound(service.findById(id)); + + eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response)); + return resourceById; + } + catch (MyResourceNotFoundException exc) { + throw new ResponseStatusException( + HttpStatus.NOT_FOUND, "Foo Not Found", exc); + } - eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response)); - return resourceById; } // read - all @GetMapping public List findAll() { + System.out.println(version); return service.findAll(); } @@ -120,7 +134,7 @@ public class FooController { @ResponseStatus(HttpStatus.OK) public void update(@PathVariable("id") final Long id, @RequestBody final Foo resource) { Preconditions.checkNotNull(resource); - RestPreconditions.checkFound(service.findOne(resource.getId())); + RestPreconditions.checkFound(service.findById(resource.getId())); service.update(resource); } diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java index 436e41e8eb..d618e9f0bf 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/RootController.java @@ -7,34 +7,28 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.util.UriTemplate; import com.baeldung.web.util.LinkUtil; @Controller -@RequestMapping(value = "/auth/") public class RootController { - public RootController() { - super(); - } - // API // discover - @RequestMapping(value = "admin", method = RequestMethod.GET) + @GetMapping("/") @ResponseStatus(value = HttpStatus.NO_CONTENT) public void adminRoot(final HttpServletRequest request, final HttpServletResponse response) { final String rootUri = request.getRequestURL() .toString(); - final URI fooUri = new UriTemplate("{rootUri}/{resource}").expand(rootUri, "foo"); - final String linkToFoo = LinkUtil.createLinkHeader(fooUri.toASCIIString(), "collection"); - response.addHeader("Link", linkToFoo); + final URI fooUri = new UriTemplate("{rootUri}{resource}").expand(rootUri, "foos"); + final String linkToFoos = LinkUtil.createLinkHeader(fooUri.toASCIIString(), "collection"); + response.addHeader("Link", linkToFoos); } } diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java index 31555ef353..afcd364cce 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/hateoas/listener/PaginatedResultsRetrievedDiscoverabilityListener.java @@ -115,7 +115,7 @@ class PaginatedResultsRetrievedDiscoverabilityListener implements ApplicationLis protected void plural(final UriComponentsBuilder uriBuilder, final Class clazz) { final String resourceName = clazz.getSimpleName() .toLowerCase() + "s"; - uriBuilder.path("/auth/" + resourceName); + uriBuilder.path("/" + resourceName); } } diff --git a/spring-boot-rest/src/main/resources/application.properties b/spring-boot-rest/src/main/resources/application.properties index a0179f1e4b..6ac3c2ebd2 100644 --- a/spring-boot-rest/src/main/resources/application.properties +++ b/spring-boot-rest/src/main/resources/application.properties @@ -1,6 +1,7 @@ -server.port=8082 server.servlet.context-path=/spring-boot-rest ### Spring Boot default error handling configurations #server.error.whitelabel.enabled=false -#server.error.include-stacktrace=always \ No newline at end of file +#server.error.include-stacktrace=always + +version=1 \ No newline at end of file diff --git a/spring-boot-rest/src/test/java/com/baeldung/Consts.java b/spring-boot-rest/src/test/java/com/baeldung/Consts.java index e33efd589e..4850a1b36a 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/Consts.java +++ b/spring-boot-rest/src/test/java/com/baeldung/Consts.java @@ -1,5 +1,5 @@ package com.baeldung; public interface Consts { - int APPLICATION_PORT = 8082; + int APPLICATION_PORT = 8080; } diff --git a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java index d26632bc38..18f612d398 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/common/web/AbstractLiveTest.java @@ -59,7 +59,7 @@ public abstract class AbstractLiveTest { // protected String getURL() { - return "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/auth/foos"; + return "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/foos"; } } diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java index bd5b5eb58e..3300b91fde 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerAppIntegrationTest.java @@ -27,7 +27,7 @@ public class FooControllerAppIntegrationTest { @Test public void whenFindPaginatedRequest_thenEmptyResponse() throws Exception { - this.mockMvc.perform(get("/auth/foos").param("page", "0") + this.mockMvc.perform(get("/foos").param("page", "0") .param("size", "2")) .andExpect(status().isOk()) .andExpect(content().json("[]")); diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java index dc48c21b30..9e7b60ed8c 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerCustomEtagIntegrationTest.java @@ -29,7 +29,7 @@ public class FooControllerCustomEtagIntegrationTest { @Autowired private MockMvc mvc; - private String FOOS_ENDPOINT = "/auth/foos/"; + private String FOOS_ENDPOINT = "/foos/"; private String CUSTOM_ETAG_ENDPOINT_SUFFIX = "/custom-etag"; private static String serializeFoo(Foo foo) throws Exception { diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java index 7e41cf6393..bd98523b0a 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooControllerWebLayerIntegrationTest.java @@ -51,7 +51,7 @@ public class FooControllerWebLayerIntegrationTest { doNothing().when(publisher) .publishEvent(any(PaginatedResultsRetrievedEvent.class)); - this.mockMvc.perform(get("/auth/foos").param("page", "0") + this.mockMvc.perform(get("/foos").param("page", "0") .param("size", "2")) .andExpect(status().isOk()) .andExpect(jsonPath("$",Matchers.hasSize(1))); diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java index 359a62a4d8..6a365f3bd5 100644 --- a/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java +++ b/spring-boot-rest/src/test/java/com/baeldung/web/FooPageableLiveTest.java @@ -74,7 +74,7 @@ public class FooPageableLiveTest extends AbstractBasicLiveTest { } protected String getPageableURL() { - return "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/auth/foos/pageable"; + return "http://localhost:" + APPLICATION_PORT + "/spring-boot-rest/foos/pageable"; } } diff --git a/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json b/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json index 5a6230bd22..dc4acafab3 100644 --- a/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json +++ b/spring-boot-rest/src/test/resources/foo_API_test.postman_collection.json @@ -42,15 +42,14 @@ "raw": "{\n \"name\": \"Transformers\"\n}" }, "url": { - "raw": "http://localhost:8082/spring-boot-rest/auth/foos", + "raw": "http://localhost:8080/spring-boot-rest/foos", "protocol": "http", "host": [ "localhost" ], - "port": "8082", + "port": "8080", "path": [ "spring-boot-rest", - "auth", "foos" ] } @@ -85,15 +84,14 @@ "raw": "" }, "url": { - "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "raw": "http://localhost:8080/spring-boot-rest/foos/{{id}}", "protocol": "http", "host": [ "localhost" ], - "port": "8082", + "port": "8080", "path": [ "spring-boot-rest", - "auth", "foos", "{{id}}" ] @@ -123,15 +121,14 @@ "raw": "" }, "url": { - "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "raw": "http://localhost:8080/spring-boot-rest/foos/{{id}}", "protocol": "http", "host": [ "localhost" ], - "port": "8082", + "port": "8080", "path": [ "spring-boot-rest", - "auth", "foos", "{{id}}" ] @@ -164,15 +161,14 @@ "raw": "" }, "url": { - "raw": "http://localhost:8082/spring-boot-rest/auth/foos/{{id}}", + "raw": "http://localhost:8080/spring-boot-rest/foos/{{id}}", "protocol": "http", "host": [ "localhost" ], - "port": "8082", + "port": "8080", "path": [ "spring-boot-rest", - "auth", "foos", "{{id}}" ] From af544b87364c8763d1f065a542d13360298cb420 Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 17 Mar 2019 12:27:29 +0200 Subject: [PATCH 375/496] remove extra import --- .../src/main/java/com/baeldung/SpringBootRestApplication.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java index 496f6acdfa..62aae7619d 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java +++ b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java @@ -1,13 +1,11 @@ package com.baeldung; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootRestApplication { - public static void main(String[] args) { SpringApplication.run(SpringBootRestApplication.class, args); } From 20002723abe8ad4b1b919031a82d4ba0ba1437e9 Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 17 Mar 2019 12:28:28 +0200 Subject: [PATCH 376/496] remove extra import --- .../java/com/baeldung/web/controller/FooController.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java index 0162d561b4..8174480078 100644 --- a/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/FooController.java @@ -5,7 +5,6 @@ import java.util.List; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -42,10 +41,6 @@ public class FooController { @Autowired private IFooService service; - - - @Value("${version}") - Integer version; public FooController() { super(); @@ -86,7 +81,6 @@ public class FooController { @GetMapping public List findAll() { - System.out.println(version); return service.findAll(); } From 7895993ee4bb0f2887945285a0b2351d675b052a Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 17 Mar 2019 12:29:40 +0200 Subject: [PATCH 377/496] remove extra config --- spring-boot-rest/src/main/resources/application.properties | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-boot-rest/src/main/resources/application.properties b/spring-boot-rest/src/main/resources/application.properties index 6ac3c2ebd2..176deb4f49 100644 --- a/spring-boot-rest/src/main/resources/application.properties +++ b/spring-boot-rest/src/main/resources/application.properties @@ -3,5 +3,3 @@ server.servlet.context-path=/spring-boot-rest ### Spring Boot default error handling configurations #server.error.whitelabel.enabled=false #server.error.include-stacktrace=always - -version=1 \ No newline at end of file From acfe84689c36a7f0054624053a9d2933ffc8084c Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sun, 17 Mar 2019 12:33:21 +0200 Subject: [PATCH 378/496] Update pom.xml --- testing-modules/rest-assured/pom.xml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/testing-modules/rest-assured/pom.xml b/testing-modules/rest-assured/pom.xml index 8128cd0b3f..5d3cac4aa3 100644 --- a/testing-modules/rest-assured/pom.xml +++ b/testing-modules/rest-assured/pom.xml @@ -15,20 +15,20 @@ - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-test - test - - - com.google.guava - guava - ${guava.version} - + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + com.google.guava + guava + ${guava.version} + javax.servlet javax.servlet-api From 78bb153e4da39e6c8afcbaa4c73495e2e313d171 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 17 Mar 2019 17:37:42 +0530 Subject: [PATCH 379/496] [BAEL-10982] - Moved live tests to spring-rest-simple and added missing methods in FooController for that --- .../web/controller/FooController.java | 40 ++++++++++++++++++- .../web/test}/RestTemplateBasicLiveTest.java | 10 ++--- .../test}/TestRestTemplateBasicLiveTest.java | 2 +- 3 files changed, 44 insertions(+), 8 deletions(-) rename {spring-resttemplate/src/test/java/org/baeldung/client => spring-rest-simple/src/test/java/org/baeldung/web/test}/RestTemplateBasicLiveTest.java (97%) rename {spring-resttemplate/src/test/java/org/baeldung/client => spring-rest-simple/src/test/java/org/baeldung/web/test}/TestRestTemplateBasicLiveTest.java (99%) diff --git a/spring-rest-simple/src/main/java/org/baeldung/web/controller/FooController.java b/spring-rest-simple/src/main/java/org/baeldung/web/controller/FooController.java index e8cb218258..c68d586667 100644 --- a/spring-rest-simple/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-rest-simple/src/main/java/org/baeldung/web/controller/FooController.java @@ -2,12 +2,21 @@ package org.baeldung.web.controller; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import java.util.List; + import org.baeldung.web.dto.Foo; import org.baeldung.web.dto.FooProtos; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.ResponseStatus; + +import com.google.common.collect.Lists; @Controller public class FooController { @@ -16,6 +25,12 @@ public class FooController { super(); } + @RequestMapping(method = RequestMethod.GET, value = "/foos") + @ResponseBody + public List findListOfFoo() { + return Lists.newArrayList(new Foo(1, randomAlphabetic(4))); + } + // API - read @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") @@ -32,6 +47,27 @@ public class FooController { public Foo updateFoo(@PathVariable("id") final String id, @RequestBody final Foo foo) { return foo; } + + @RequestMapping(method = RequestMethod.PATCH, value = "/foos/{id}") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public Foo patchFoo(@PathVariable("id") final String id, @RequestBody final Foo foo) { + return foo; + } + + @RequestMapping(method = RequestMethod.POST, value = "/foos") + @ResponseStatus(HttpStatus.CREATED) + @ResponseBody + public Foo postFoo(@RequestBody final Foo foo) { + return foo; + } + + @RequestMapping(method = RequestMethod.HEAD, value = "/foos") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public Foo headFoo() { + return new Foo(1, randomAlphabetic(4)); + } @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}", produces = { "application/x-protobuf" }) @ResponseBody diff --git a/spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java b/spring-rest-simple/src/test/java/org/baeldung/web/test/RestTemplateBasicLiveTest.java similarity index 97% rename from spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java rename to spring-rest-simple/src/test/java/org/baeldung/web/test/RestTemplateBasicLiveTest.java index c837e23547..e213d0255f 100644 --- a/spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java +++ b/spring-rest-simple/src/test/java/org/baeldung/web/test/RestTemplateBasicLiveTest.java @@ -1,7 +1,6 @@ -package org.baeldung.client; +package org.baeldung.web.test; import static org.apache.commons.codec.binary.Base64.encodeBase64; -import static org.baeldung.client.Consts.APPLICATION_PORT; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -14,7 +13,7 @@ import java.net.URI; import java.util.Arrays; import java.util.Set; -import org.baeldung.resttemplate.web.dto.Foo; +import org.baeldung.web.dto.Foo; import org.junit.Before; import org.junit.Test; import org.springframework.http.HttpEntity; @@ -34,12 +33,13 @@ import org.springframework.web.client.RestTemplate; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.google.common.base.Charsets; public class RestTemplateBasicLiveTest { private RestTemplate restTemplate; - private static final String fooResourceUrl = "http://localhost:" + APPLICATION_PORT + "/spring-rest/foos"; + private static final String fooResourceUrl = "http://localhost:8082/spring-rest/foos"; @Before public void beforeTest() { @@ -61,7 +61,7 @@ public class RestTemplateBasicLiveTest { final RestTemplate template = new RestTemplate(); final ResponseEntity response = template.getForEntity(fooResourceUrl + "/1", String.class); - final ObjectMapper mapper = new ObjectMapper(); + final ObjectMapper mapper = new XmlMapper(); final JsonNode root = mapper.readTree(response.getBody()); final JsonNode name = root.path("name"); assertThat(name.asText(), notNullValue()); diff --git a/spring-resttemplate/src/test/java/org/baeldung/client/TestRestTemplateBasicLiveTest.java b/spring-rest-simple/src/test/java/org/baeldung/web/test/TestRestTemplateBasicLiveTest.java similarity index 99% rename from spring-resttemplate/src/test/java/org/baeldung/client/TestRestTemplateBasicLiveTest.java rename to spring-rest-simple/src/test/java/org/baeldung/web/test/TestRestTemplateBasicLiveTest.java index e303c75a28..b920ed38da 100644 --- a/spring-resttemplate/src/test/java/org/baeldung/client/TestRestTemplateBasicLiveTest.java +++ b/spring-rest-simple/src/test/java/org/baeldung/web/test/TestRestTemplateBasicLiveTest.java @@ -1,4 +1,4 @@ -package org.baeldung.client; +package org.baeldung.web.test; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; From 10e9cbda1ea7dc9e7f91319d0fa0178bee5a2e52 Mon Sep 17 00:00:00 2001 From: juanvaccari Date: Mon, 18 Mar 2019 01:01:40 +0000 Subject: [PATCH 380/496] BAEL-2650 - Kotlin standard functions: run, with, let, also and apply (#6553) --- .../com/baeldung/scope/ScopeFunctions.kt | 25 ++++ .../baeldung/scope/ScopeFunctionsUnitTest.kt | 119 ++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 core-kotlin-2/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt create mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt b/core-kotlin-2/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt new file mode 100644 index 0000000000..37ad8c65e2 --- /dev/null +++ b/core-kotlin-2/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt @@ -0,0 +1,25 @@ +package com.baeldung.scope + +data class Student(var studentId: String = "", var name: String = "", var surname: String = "") { +} + +data class Teacher(var teacherId: Int = 0, var name: String = "", var surname: String = "") { + fun setId(anId: Int): Teacher = apply { teacherId = anId } + fun setName(aName: String): Teacher = apply { name = aName } + fun setSurname(aSurname: String): Teacher = apply { surname = aSurname } +} + +data class Headers(val headerInfo: String) + +data class Response(val headers: Headers) + +data class RestClient(val url: String) { + fun getResponse() = Response(Headers("some header info")) +} + +data class BankAccount(val id: Int) { + fun checkAuthorization(username: String) = Unit + fun addPayee(payee: String) = Unit + fun makePayment(paymentDetails: String) = Unit + +} \ No newline at end of file diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt new file mode 100644 index 0000000000..ef082655eb --- /dev/null +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt @@ -0,0 +1,119 @@ +package com.baeldung.scope + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + +class ScopeFunctionsUnitTest { + + class Logger { + + var called : Boolean = false + + fun info(message: String) { + called = true + } + + fun wasCalled() = called + } + + @Test + fun shouldTransformWhenLetFunctionUsed() { + val stringBuider = StringBuilder() + val numberOfCharacters = stringBuider.let { + it.append("This is a transformation function.") + it.append("It takes a StringBuilder instance and returns the number of characters in the generated String") + it.length + } + assertThat(numberOfCharacters).isEqualTo(128) + } + + @Test + fun shouldHandleNullabilityWhenLetFunctionUsed() { + + val message: String? = "hello there!" + val charactersInMessage = message?.let { + "At this point is safe to reference the variable. Let's print the message: $it" + } ?: "default value" + + assertThat(charactersInMessage).isEqualTo("At this point is safe to reference the variable. Let's print the message: hello there!") + + val aNullMessage = null + val thisIsNull = aNullMessage?.let { + "At this point it would be safe to reference the variable. But it will not really happen because it is null. Let's reference: $it" + } ?: "default value" + + assertThat(thisIsNull).isEqualTo("default value") + } + + @Test + fun shouldInitializeObjectWhenUsingApply() { + val aStudent = Student().apply { + studentId = "1234567" + name = "Mary" + surname = "Smith" + } + assertThat(aStudent.name).isEqualTo("Mary") + } + + @Test + fun shouldAllowBuilderStyleObjectDesignWhenApplyUsedInClassMethods() { + val teacher = Teacher() + .setId(1000) + .setName("Martha") + .setSurname("Spector") + + assertThat(teacher.surname).isEqualTo("Spector") + } + + @Test + fun shouldAllowSideEffectWhenUsingAlso() { + val restClient = RestClient("http://www.someurl.com") + + val logger = Logger() + + val headers = restClient + .getResponse() + .also { logger.info(it.toString()) } + .headers + + assertThat(logger.wasCalled()).isTrue() + assertThat(headers.headerInfo).isEqualTo("some header info") + } + + @Test + fun shouldInitializeFieldWhenAlsoUsed() { + val aStudent = Student().also { it.name = "John"} + assertThat(aStudent.name).isEqualTo("John") + } + + @Test + fun shouldLogicallyGroupObjectCallsWhenUsingWith() { + val bankAccount = BankAccount(1000) + with (bankAccount) { + checkAuthorization("someone") + addPayee("some payee") + makePayment("payment information") + } + } + + @Test + fun shouldConvertObjectWhenRunUsed() { + val stringBuider = StringBuilder() + val numberOfCharacters = stringBuider.run { + append("This is a transformation function.") + append("It takes a StringBuilder instance and returns the number of characters in the generated String") + length + } + assertThat(numberOfCharacters).isEqualTo(128) + } + + @Test + fun shouldHandleNullabilityWhenRunIsUsed() { + val message: String? = "hello there!" + val charactersInMessage = message?.run { + "At this point is safe to reference the variable. Let's print the message: $this" + } ?: "default value" + assertThat(charactersInMessage).isEqualTo("At this point is safe to reference the variable. Let's print the message: hello there!") + } + +} \ No newline at end of file From 16fdea72679c2d52f3bb4a9d4e6ecf56a8ad8873 Mon Sep 17 00:00:00 2001 From: pcoates33 Date: Mon, 18 Mar 2019 06:56:13 +0000 Subject: [PATCH 381/496] BAEL-2721 Moved JsonAliasUnitTest into new module called jackson-2. (#6555) * BAEL-2721 Examples of @JsonAlias and Gson's alternate parameter * BAEL-2721 Update class and method names for JsonAlias and GsonAlternate * BAEL-2721 move JsonAliasUnitTest into new jackson-2 module * BAEL-2721 Removed unused dependencies from pom.xml * BAEL-2721 Tidy up logback.xml * BAEL-2721 fix url in README.md --- gson/README.md | 2 + jackson-2/.gitignore | 13 +++++ jackson-2/README.md | 9 ++++ jackson-2/pom.xml | 52 +++++++++++++++++++ .../baeldung/jackson/entities/Weather.java | 0 jackson-2/src/main/resources/logback.xml | 13 +++++ .../jsonalias/JsonAliasUnitTest.java | 0 pom.xml | 2 + 8 files changed, 91 insertions(+) create mode 100644 jackson-2/.gitignore create mode 100644 jackson-2/README.md create mode 100644 jackson-2/pom.xml rename {jackson => jackson-2}/src/main/java/com/baeldung/jackson/entities/Weather.java (100%) create mode 100644 jackson-2/src/main/resources/logback.xml rename {jackson => jackson-2}/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java (100%) diff --git a/gson/README.md b/gson/README.md index 02b06eac20..665ccb552b 100644 --- a/gson/README.md +++ b/gson/README.md @@ -11,3 +11,5 @@ - [Convert JSON to a Map Using Gson](https://www.baeldung.com/gson-json-to-map) - [Working with Primitive Values in Gson](https://www.baeldung.com/java-gson-primitives) - [Convert String to JsonObject with Gson](https://www.baeldung.com/gson-string-to-jsonobject) +- [Mapping Multiple JSON Fields to One Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) + diff --git a/jackson-2/.gitignore b/jackson-2/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/jackson-2/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/jackson-2/README.md b/jackson-2/README.md new file mode 100644 index 0000000000..7c14bcfd19 --- /dev/null +++ b/jackson-2/README.md @@ -0,0 +1,9 @@ +========= + +## Jackson Cookbooks and Examples + +###The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: +- [Mapping Multiple JSON Fields to One Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) \ No newline at end of file diff --git a/jackson-2/pom.xml b/jackson-2/pom.xml new file mode 100644 index 0000000000..ddbcb81dcc --- /dev/null +++ b/jackson-2/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + jackson-2 + 0.1-SNAPSHOT + jackson-2 + + + com.baeldung + parent-java + 0.0.1-SNAPSHOT + ../parent-java + + + + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + jackson-2 + + + src/main/resources + true + + + + + + + + 3.11.0 + + + diff --git a/jackson/src/main/java/com/baeldung/jackson/entities/Weather.java b/jackson-2/src/main/java/com/baeldung/jackson/entities/Weather.java similarity index 100% rename from jackson/src/main/java/com/baeldung/jackson/entities/Weather.java rename to jackson-2/src/main/java/com/baeldung/jackson/entities/Weather.java diff --git a/jackson-2/src/main/resources/logback.xml b/jackson-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/jackson-2/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/jackson/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java similarity index 100% rename from jackson/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java rename to jackson-2/src/test/java/com/baeldung/jackson/deserialization/jsonalias/JsonAliasUnitTest.java diff --git a/pom.xml b/pom.xml index 5858df01e1..d29824b085 100644 --- a/pom.xml +++ b/pom.xml @@ -436,6 +436,7 @@ immutables jackson + jackson-2 java-collections-conversions java-collections-maps @@ -1078,6 +1079,7 @@ immutables jackson + jackson-2 java-collections-conversions java-collections-maps From bd227fd9fe7ed8a2cd4b24ba7aa41355164ae650 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 16:00:24 +0800 Subject: [PATCH 382/496] Update README.md --- core-java-9/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-9/README.md b/core-java-9/README.md index fb7f69dc42..9ce419b054 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -27,3 +27,4 @@ - [Immutable Set in Java](https://www.baeldung.com/java-immutable-set) - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) - [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation) +- [Java 9 Process API Improvements](https://www.baeldung.com/java-9-process-api) From d2a1c0a141e758451cee1a55389ceb7f2cf98403 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 16:07:20 +0800 Subject: [PATCH 383/496] Update README.md --- core-java-concurrency-basic/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-concurrency-basic/README.md b/core-java-concurrency-basic/README.md index ad3de4a758..7d106095e7 100644 --- a/core-java-concurrency-basic/README.md +++ b/core-java-concurrency-basic/README.md @@ -16,3 +16,4 @@ - [Life Cycle of a Thread in Java](http://www.baeldung.com/java-thread-lifecycle) - [Runnable vs. Callable in Java](http://www.baeldung.com/java-runnable-callable) - [What is Thread-Safety and How to Achieve it](https://www.baeldung.com/java-thread-safety) +- [How to Start a Thread in Java](https://www.baeldung.com/java-start-thread) From 94dcd557b31fcc7710f87f6b56fc31005ec8159b Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 16:20:29 +0800 Subject: [PATCH 384/496] Update README.MD --- spring-boot/README.MD | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot/README.MD b/spring-boot/README.MD index 223e0959fc..b5f0bf39b6 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -37,3 +37,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Injecting Git Information Into Spring](https://www.baeldung.com/spring-git-information) - [Validation in Spring Boot](https://www.baeldung.com/spring-boot-bean-validation) - [Entity To DTO Conversion for a Spring REST API](https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application) +- [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) From 56b3e923ccf17ef282153bcc568c4464b2f610eb Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 16:26:48 +0800 Subject: [PATCH 385/496] Update README.md --- spring-core/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-core/README.md b/spring-core/README.md index dcc15a4cb9..d542fa8ed1 100644 --- a/spring-core/README.md +++ b/spring-core/README.md @@ -23,3 +23,4 @@ - [Unsatisfied Dependency in Spring](https://www.baeldung.com/spring-unsatisfied-dependency) - [What is a Spring Bean?](https://www.baeldung.com/spring-bean) - [Spring PostConstruct and PreDestroy Annotations](https://www.baeldung.com/spring-postconstruct-predestroy) +- [Guice vs Spring – Dependency Injection](https://www.baeldung.com/guice-spring-dependency-injection) From 03878d1ba655e2a9fa29b324c0f9882485bf80c0 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 16:38:10 +0800 Subject: [PATCH 386/496] Update README.md --- core-kotlin-2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-kotlin-2/README.md b/core-kotlin-2/README.md index da2f7548d9..4ac1c2c7bb 100644 --- a/core-kotlin-2/README.md +++ b/core-kotlin-2/README.md @@ -3,4 +3,4 @@ - [Void Type in Kotlin](https://www.baeldung.com/kotlin-void-type) - [How to use Kotlin Range Expressions](https://www.baeldung.com/kotlin-ranges) - [Split a List into Parts in Kotlin](https://www.baeldung.com/kotlin-split-list-into-parts) - +- [String Comparison in Kotlin](https://www.baeldung.com/kotlin-string-comparison) From 0c15700730fb21130e435688fa176fb514044f73 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 17:09:38 +0800 Subject: [PATCH 387/496] Update README.md --- spring-5-reactive/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-5-reactive/README.md b/spring-5-reactive/README.md index ef2f7d07eb..538a15c879 100644 --- a/spring-5-reactive/README.md +++ b/spring-5-reactive/README.md @@ -19,3 +19,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Logging a Reactive Sequence](https://www.baeldung.com/spring-reactive-sequence-logging) - [Testing Reactive Streams Using StepVerifier and TestPublisher](https://www.baeldung.com/reactive-streams-step-verifier-test-publisher) - [Debugging Reactive Streams in Spring 5](https://www.baeldung.com/spring-debugging-reactive-streams) +- [Static Content in Spring WebFlux](https://www.baeldung.com/spring-webflux-static-content) From c4fae305aa914ff787510a835891a8f24c0de675 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 17:18:08 +0800 Subject: [PATCH 388/496] Update README.md --- spring-boot-rest/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md index 8fbc9527b8..af372077f0 100644 --- a/spring-boot-rest/README.md +++ b/spring-boot-rest/README.md @@ -10,3 +10,4 @@ Module for the articles that are part of the Spring REST E-book: 8. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) 9. [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) 10. [Testing REST with multiple MIME types](http://www.baeldung.com/testing-rest-api-with-multiple-media-types) +11. [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections) From ade2fb6206ace7978b2cda690317815cf7598be1 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 17:24:02 +0800 Subject: [PATCH 389/496] Update README.md --- java-streams/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java-streams/README.md b/java-streams/README.md index b931c0d7d9..e294e5aee1 100644 --- a/java-streams/README.md +++ b/java-streams/README.md @@ -17,3 +17,4 @@ - [Java Stream Filter with Lambda Expression](https://www.baeldung.com/java-stream-filter-lambda) - [Counting Matches on a Stream Filter](https://www.baeldung.com/java-stream-filter-count) - [Java 8 Streams peek() API](https://www.baeldung.com/java-streams-peek-api) +- [Working With Maps Using Streams](https://www.baeldung.com/java-maps-streams) From a15e932348e1912593ddda9cba5c64a609190876 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 17:47:11 +0800 Subject: [PATCH 390/496] Update README.md --- persistence-modules/core-java-persistence/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/core-java-persistence/README.md b/persistence-modules/core-java-persistence/README.md index ca0ce81eef..26bd4bf00f 100644 --- a/persistence-modules/core-java-persistence/README.md +++ b/persistence-modules/core-java-persistence/README.md @@ -7,3 +7,4 @@ - [Batch Processing in JDBC](http://www.baeldung.com/jdbc-batch-processing) - [Introduction to the JDBC RowSet Interface in Java](http://www.baeldung.com/java-jdbc-rowset) - [A Simple Guide to Connection Pooling in Java](https://www.baeldung.com/java-connection-pooling) +- [Guide to the JDBC ResultSet Interface](https://www.baeldung.com/jdbc-resultset) From 2e6628e2b859b463a1a0d7e619c23dcd863624bf Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 17:51:48 +0800 Subject: [PATCH 391/496] Update README.md --- core-kotlin/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-kotlin/README.md b/core-kotlin/README.md index 95c57336b9..73a78eccff 100644 --- a/core-kotlin/README.md +++ b/core-kotlin/README.md @@ -55,3 +55,4 @@ - [Building DSLs in Kotlin](https://www.baeldung.com/kotlin-dsl) - [Static Methods Behavior in Kotlin](https://www.baeldung.com/kotlin-static-methods) - [Inline Functions in Kotlin](https://www.baeldung.com/kotlin-inline-functions) +- [Delegation Pattern in Kotlin](https://www.baeldung.com/kotlin-delegation-pattern) From 55ecf4181e614a621b89d12e55d226d0daf34ac0 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 18:36:42 +0800 Subject: [PATCH 392/496] Update README.md --- spring-cloud/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-cloud/README.md b/spring-cloud/README.md index fede3cc12d..5139cdca20 100644 --- a/spring-cloud/README.md +++ b/spring-cloud/README.md @@ -17,4 +17,5 @@ - [Dockerizing a Spring Boot Application](http://www.baeldung.com/dockerizing-spring-boot-application) - [Instance Profile Credentials using Spring Cloud](http://www.baeldung.com/spring-cloud-instance-profiles) - [Running Spring Boot Applications With Minikube](http://www.baeldung.com/spring-boot-minikube) +- [Introduction to Spring Cloud OpenFeign](https://www.baeldung.com/spring-cloud-openfeign) From 7edf996098be5d555cdca0dce360a23c2a95a9f7 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 18:46:23 +0800 Subject: [PATCH 393/496] Update README.md --- core-java-11/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-11/README.md b/core-java-11/README.md index 5e2c07178b..b09649f4f1 100644 --- a/core-java-11/README.md +++ b/core-java-11/README.md @@ -5,3 +5,4 @@ - [Java 11 String API Additions](https://www.baeldung.com/java-11-string-api) - [Java 11 Nest Based Access Control](https://www.baeldung.com/java-nest-based-access-control) - [Exploring the New HTTP Client in Java 9 and 11](https://www.baeldung.com/java-9-http-client) +- [An Introduction to Epsilon GC: A No-Op Experimental Garbage Collector](https://www.baeldung.com/jvm-epsilon-gc-garbage-collector) From 3fd366713ead382aac3740b4181ef9f66f4a0453 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 18:48:48 +0800 Subject: [PATCH 394/496] Update README.md --- persistence-modules/java-jpa/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/java-jpa/README.md b/persistence-modules/java-jpa/README.md index 2c26581bab..2424999fb3 100644 --- a/persistence-modules/java-jpa/README.md +++ b/persistence-modules/java-jpa/README.md @@ -6,3 +6,4 @@ - [JPA Entity Graph](https://www.baeldung.com/jpa-entity-graph) - [JPA 2.2 Support for Java 8 Date/Time Types](https://www.baeldung.com/jpa-java-time) - [Converting Between LocalDate and SQL Date](https://www.baeldung.com/java-convert-localdate-sql-date) +- [Combining JPA And/Or Criteria Predicates](https://www.baeldung.com/jpa-and-or-criteria-predicates) From 6b0ea75cda35af9ad49e8512d371ca9ae1bb5a5d Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 18:50:24 +0800 Subject: [PATCH 395/496] Update README.md --- patterns/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/patterns/README.md b/patterns/README.md index 9a15cdff02..1c9a59ea21 100644 --- a/patterns/README.md +++ b/patterns/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [A Guide to the Front Controller Pattern in Java](http://www.baeldung.com/java-front-controller-pattern) - [Introduction to Intercepting Filter Pattern in Java](http://www.baeldung.com/intercepting-filter-pattern-in-java) +- [Introduction to the Null Object Pattern](https://www.baeldung.com/java-null-object-pattern) From 8d6ac99ac2d9e5877e1bf10eaf96b201d4fa793f Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 18:56:11 +0800 Subject: [PATCH 396/496] Update README.md --- core-groovy/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-groovy/README.md b/core-groovy/README.md index bac91bf028..542f296d28 100644 --- a/core-groovy/README.md +++ b/core-groovy/README.md @@ -9,3 +9,4 @@ - [A Quick Guide to Iterating a Map in Groovy](https://www.baeldung.com/groovy-map-iterating) - [An Introduction to Traits in Groovy](https://www.baeldung.com/groovy-traits) - [Lists in Groovy](https://www.baeldung.com/groovy-lists) +- [Converting a String to a Date in Groovy](https://www.baeldung.com/groovy-string-to-date) From ef210e58bc7632ac9736b77110eda8fa1583c841 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 18:59:17 +0800 Subject: [PATCH 397/496] Update README.md --- core-groovy/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-groovy/README.md b/core-groovy/README.md index 542f296d28..606a317747 100644 --- a/core-groovy/README.md +++ b/core-groovy/README.md @@ -10,3 +10,4 @@ - [An Introduction to Traits in Groovy](https://www.baeldung.com/groovy-traits) - [Lists in Groovy](https://www.baeldung.com/groovy-lists) - [Converting a String to a Date in Groovy](https://www.baeldung.com/groovy-string-to-date) +- [Guide to I/O in Groovy](https://www.baeldung.com/groovy-io) From b7c193105969cb1f6f8d185843fc459c2ec283f8 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:02:55 +0800 Subject: [PATCH 398/496] Update README.md --- persistence-modules/spring-data-jpa/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md index 9512ad336d..48c3180262 100644 --- a/persistence-modules/spring-data-jpa/README.md +++ b/persistence-modules/spring-data-jpa/README.md @@ -22,6 +22,7 @@ - [Spring Data JPA Query by Example](https://www.baeldung.com/spring-data-query-by-example) - [DB Integration Tests with Spring Boot and Testcontainers](https://www.baeldung.com/spring-boot-testcontainers-integration-test) - [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) +- [Spring Data JPA Batch Inserts](https://www.baeldung.com/spring-data-jpa-batch-inserts) ### Eclipse Config After importing the project into Eclipse, you may see the following error: From 045f45ebd5238b51eec702e5b73764041f79f34d Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:05:47 +0800 Subject: [PATCH 399/496] Update README.md --- core-java/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java/README.md b/core-java/README.md index e1325ab29f..cbc9251b0b 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -50,3 +50,4 @@ - [Finding Leap Years in Java](https://www.baeldung.com/java-leap-year) - [Java Bitwise Operators](https://www.baeldung.com/java-bitwise-operators) - [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) +- [Making a JSON POST Request With HttpURLConnection](https://www.baeldung.com/httpurlconnection-post) From 6868bcdf3ccba30056d9c0988647145172d4f2f8 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:09:15 +0800 Subject: [PATCH 400/496] Update README.md --- spring-boot-ops/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spring-boot-ops/README.md b/spring-boot-ops/README.md index 553b02ebf0..d5063f14e5 100644 --- a/spring-boot-ops/README.md +++ b/spring-boot-ops/README.md @@ -10,3 +10,5 @@ - [Spring Boot Console Application](http://www.baeldung.com/spring-boot-console-app) - [Comparing Embedded Servlet Containers in Spring Boot](http://www.baeldung.com/spring-boot-servlet-containers) - [Programmatically Restarting a Spring Boot Application](https://www.baeldung.com/java-restart-spring-boot-app) + - [Spring Properties File Outside jar](https://www.baeldung.com/spring-properties-file-outside-jar) + From 126e4e421ae763e1b50e8290f3835f3328d51a41 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:12:23 +0800 Subject: [PATCH 401/496] Update README.md --- jackson/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/jackson/README.md b/jackson/README.md index e9cf6f212c..15af88fe26 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -39,4 +39,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Convert XML to JSON Using Jackson](https://www.baeldung.com/jackson-convert-xml-json) - [Deserialize Immutable Objects with Jackson](https://www.baeldung.com/jackson-deserialize-immutable-objects) - [Mapping a Dynamic JSON Object with Jackson](https://www.baeldung.com/jackson-mapping-dynamic-object) +- [Mapping Multiple JSON Fields to a Single Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) From 2cb74787f38640a98d93ea1b17948030ea589773 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:14:58 +0800 Subject: [PATCH 402/496] Update README.md --- reactor-core/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/reactor-core/README.md b/reactor-core/README.md index 6f90e59894..5f9d2d1bc2 100644 --- a/reactor-core/README.md +++ b/reactor-core/README.md @@ -2,3 +2,4 @@ - [Intro To Reactor Core](http://www.baeldung.com/reactor-core) - [Combining Publishers in Project Reactor](http://www.baeldung.com/reactor-combine-streams) +- [Programmatically Creating Sequences with Project Reactor](https://www.baeldung.com/flux-sequences-reactor) From 2f2fdccd6bd1737880144c793a6cadae00a61b7d Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:17:00 +0800 Subject: [PATCH 403/496] Update README.md --- core-java-os/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core-java-os/README.md b/core-java-os/README.md index 90e1d29a58..5f5d373d9b 100644 --- a/core-java-os/README.md +++ b/core-java-os/README.md @@ -6,3 +6,5 @@ This module uses Java 9, so make sure to have the JDK 9 installed to run it. ### Relevant Articles: - [Java 9 Process API Improvements](http://www.baeldung.com/java-9-process-api) - [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) +- [Guide to java.lang.ProcessBuilder API](https://www.baeldung.com/java-lang-processbuilder-api) + From b26d95ff40f3610f1f10bcd0a4a4d9c2c0a15b19 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:26:32 +0800 Subject: [PATCH 404/496] Update README.md --- gson/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/gson/README.md b/gson/README.md index 665ccb552b..fec0506488 100644 --- a/gson/README.md +++ b/gson/README.md @@ -12,4 +12,5 @@ - [Working with Primitive Values in Gson](https://www.baeldung.com/java-gson-primitives) - [Convert String to JsonObject with Gson](https://www.baeldung.com/gson-string-to-jsonobject) - [Mapping Multiple JSON Fields to One Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) +- [Serializing and Deserializing a List with Gson](https://www.baeldung.com/gson-list) From bf54fdee959350d139af64c116a8064b5c24a09f Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:29:10 +0800 Subject: [PATCH 405/496] Update README.md --- maven/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/maven/README.md b/maven/README.md index 1352a2a10f..ca648ec203 100644 --- a/maven/README.md +++ b/maven/README.md @@ -15,3 +15,4 @@ - [Use the Latest Version of a Dependency in Maven](https://www.baeldung.com/maven-dependency-latest-version) - [Multi-Module Project with Maven](https://www.baeldung.com/maven-multi-module) - [Maven Enforcer Plugin](https://www.baeldung.com/maven-enforcer-plugin) +- [Eclipse Error: web.xml is missing and failOnMissingWebXml is set to true](https://www.baeldung.com/eclipse-error-web-xml-missing) From 22c22fce869b8f36f92d0abe8c9928fbe0c087a5 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:35:11 +0800 Subject: [PATCH 406/496] Update README.md --- testing-modules/groovy-spock/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/testing-modules/groovy-spock/README.md b/testing-modules/groovy-spock/README.md index 18d26e8fc0..a98df27172 100644 --- a/testing-modules/groovy-spock/README.md +++ b/testing-modules/groovy-spock/README.md @@ -1,3 +1,4 @@ ### Relevant articles - [Introduction to Testing with Spock and Groovy](http://www.baeldung.com/groovy-spock) +- [Difference Between Stub, Mock, and Spy in the Spock Framework](https://www.baeldung.com/spock-stub-mock-spy) From f2d39cf4d9441a7772ae2d912e069bafa428476e Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Mon, 18 Mar 2019 19:38:01 +0800 Subject: [PATCH 407/496] Update README.md --- lombok/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/lombok/README.md b/lombok/README.md index e3d08d4e26..4ff7ca7921 100644 --- a/lombok/README.md +++ b/lombok/README.md @@ -6,4 +6,5 @@ - [Lombok Builder with Default Value](https://www.baeldung.com/lombok-builder-default-value) - [Lombok Builder with Custom Setter](https://www.baeldung.com/lombok-builder-custom-setter) - [Setting up Lombok with Eclipse and Intellij](https://www.baeldung.com/lombok-ide) +- [Using the @Singular Annotation with Lombok Builders](https://www.baeldung.com/lombok-builder-singular) From 4fece2266ed1f4f60aaee822111d2c2aaec68a4e Mon Sep 17 00:00:00 2001 From: caroline Date: Mon, 18 Mar 2019 14:35:22 +0100 Subject: [PATCH 408/496] Formatting changes --- .../cloud/kubernetes/client/Application.java | 17 ++- .../cloud/kubernetes/client/ClientConfig.java | 14 +- .../kubernetes/client/ClientController.java | 53 ++++---- .../client/RibbonConfiguration.java | 48 +++---- .../client/TravelAgencyService.java | 25 ++-- .../SpringContextIntegrationTest.java | 7 +- .../kubernetes/travelagency/Application.java | 2 +- .../controller/TravelAgencyController.java | 17 ++- .../travelagency/model/TravelDeal.java | 124 ++++++++---------- .../repository/TravelDealRepository.java | 1 - 10 files changed, 151 insertions(+), 157 deletions(-) diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java index de1f1ec878..24e562c79b 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java @@ -9,20 +9,19 @@ import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; - @SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker @RibbonClient(name = "travel-agency-service", configuration = RibbonConfiguration.class) public class Application { - @LoadBalanced - @Bean - RestTemplate restTemplate(){ - return new RestTemplate(); - } + @LoadBalanced + @Bean + RestTemplate restTemplate() { + return new RestTemplate(); + } - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } } diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java index 1158f3c2d2..4bc8fbe327 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java @@ -7,13 +7,13 @@ import org.springframework.context.annotation.Configuration; @ConfigurationProperties(prefix = "bean") public class ClientConfig { - private String message = "Message from backend is: %s
Services : %s"; + private String message = "Message from backend is: %s
Services : %s"; - public String getMessage() { - return message; - } + public String getMessage() { + return message; + } - public void setMessage(String message) { - this.message = message; - } + public void setMessage(String message) { + this.message = message; + } } \ No newline at end of file diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java index 44f412c31d..952bccc3a8 100755 --- a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java @@ -16,42 +16,39 @@ import java.util.List; @RestController public class ClientController { - @Autowired - private DiscoveryClient discoveryClient; + @Autowired + private DiscoveryClient discoveryClient; - @Autowired - private ClientConfig config; + @Autowired + private ClientConfig config; - @Autowired - private TravelAgencyService travelAgencyService; + @Autowired + private TravelAgencyService travelAgencyService; - @RequestMapping("/deals") - public String getDeals() { - return travelAgencyService.getDeals(); - } + @RequestMapping("/deals") + public String getDeals() { + return travelAgencyService.getDeals(); + } - @GetMapping - public String load() throws UnknownHostException { + @GetMapping + public String load() { - RestTemplate restTemplate = new RestTemplate(); - String resourceUrl - = "http://travel-agency-service:8080"; - ResponseEntity response - = restTemplate.getForEntity(resourceUrl, String.class); + RestTemplate restTemplate = new RestTemplate(); + String resourceUrl = "http://travel-agency-service:8080"; + ResponseEntity response = restTemplate.getForEntity(resourceUrl, String.class); - String serviceList = ""; - if (discoveryClient != null) { - List services = this.discoveryClient.getServices(); + String serviceList = ""; + if (discoveryClient != null) { + List services = this.discoveryClient.getServices(); - for (String service : services) { + for (String service : services) { - List instances = this.discoveryClient - .getInstances(service); + List instances = this.discoveryClient.getInstances(service); - serviceList += ("[" + service + " : " + ((!CollectionUtils.isEmpty(instances))?instances.size():0)+ " instances ]"); - } - } + serviceList += ("[" + service + " : " + ((!CollectionUtils.isEmpty(instances)) ? instances.size() : 0) + " instances ]"); + } + } - return String.format(config.getMessage(), response.getBody(),serviceList); - } + return String.format(config.getMessage(), response.getBody(), serviceList); + } } diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java index a372e9357f..2b81c78be4 100755 --- a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java @@ -26,30 +26,30 @@ import org.springframework.context.annotation.Bean; public class RibbonConfiguration { - @Autowired - IClientConfig ribbonClientConfig; + @Autowired + IClientConfig ribbonClientConfig; - /** - * PingUrl will ping a URL to check the status of each server. - * Say Hello has, as you’ll recall, a method mapped to the /path; that means that Ribbon will get an HTTP 200 response when it pings a running Backend Server - * - * @param config Client configuration - * @return The URL to be used for the Ping - */ - @Bean - public IPing ribbonPing(IClientConfig config) { - return new PingUrl(); - } + /** + * PingUrl will ping a URL to check the status of each server. + * Say Hello has, as you’ll recall, a method mapped to the /path; that means that Ribbon will get an HTTP 200 response when it pings a running Backend Server + * + * @param config Client configuration + * @return The URL to be used for the Ping + */ + @Bean + public IPing ribbonPing(IClientConfig config) { + return new PingUrl(); + } - /** - * AvailabilityFilteringRule will use Ribbon’s built-in circuit breaker functionality to filter out any servers in an “open-circuit” state: - * if a ping fails to connect to a given server, or if it gets a read failure for the server, Ribbon will consider that server “dead” until it begins to respond normally. - * - * @param config Client configuration - * @return The Load Balancer rule - */ - @Bean - public IRule ribbonRule(IClientConfig config) { - return new AvailabilityFilteringRule(); - } + /** + * AvailabilityFilteringRule will use Ribbon’s built-in circuit breaker functionality to filter out any servers in an “open-circuit” state: + * if a ping fails to connect to a given server, or if it gets a read failure for the server, Ribbon will consider that server “dead” until it begins to respond normally. + * + * @param config Client configuration + * @return The Load Balancer rule + */ + @Bean + public IRule ribbonRule(IClientConfig config) { + return new AvailabilityFilteringRule(); + } } diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java index 792699696e..9e59be4805 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java @@ -8,20 +8,19 @@ import org.springframework.web.client.RestTemplate; @Service public class TravelAgencyService { - private final RestTemplate restTemplate; + private final RestTemplate restTemplate; - public TravelAgencyService(RestTemplate restTemplate) { - this.restTemplate = restTemplate; - } + public TravelAgencyService(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } - @HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = { - @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") - }) - public String getDeals() { - return this.restTemplate.getForObject("http://travel-agency-service:8080/deals", String.class); - } + @HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = + { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") }) + public String getDeals() { + return this.restTemplate.getForObject("http://travel-agency-service:8080/deals", String.class); + } - private String getFallbackName() { - return "Fallback"; - } + private String getFallbackName() { + return "Fallback"; + } } diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java index 9dc2e4f714..a6a978a354 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -11,8 +11,7 @@ import com.baeldung.spring.cloud.kubernetes.client.Application; @SpringBootTest(classes = Application.class) public class SpringContextIntegrationTest { - @Test - public void contextLoads() { - } - + @Test + public void contextLoads() { + } } diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java index f84303a5c8..bfc7356176 100755 --- a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java @@ -8,7 +8,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class Application implements CommandLineRunner { +public class Application implements CommandLineRunner { private static final Log log = LogFactory.getLog(TravelAgencyController.class); diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java index 55a06dee77..42f001616a 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java @@ -27,7 +27,8 @@ public class TravelAgencyController { List travelDealList = travelDealRepository.findAll(); if (!travelDealList.isEmpty()) { int randomDeal = new Random().nextInt(travelDealList.size()); - return travelDealList.get(randomDeal).toString(); + return travelDealList.get(randomDeal) + .toString(); } else { return "NO DEALS"; } @@ -38,9 +39,17 @@ public class TravelAgencyController { public String get() throws UnknownHostException { StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Host: ").append(InetAddress.getLocalHost().getHostName()).append("
"); - stringBuilder.append("IP: ").append(InetAddress.getLocalHost().getHostAddress()).append("
"); - stringBuilder.append("Type: ").append("Travel Agency").append("
"); + stringBuilder.append("Host: ") + .append(InetAddress.getLocalHost() + .getHostName()) + .append("
"); + stringBuilder.append("IP: ") + .append(InetAddress.getLocalHost() + .getHostAddress()) + .append("
"); + stringBuilder.append("Type: ") + .append("Travel Agency") + .append("
"); return stringBuilder.toString(); } } diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java index 550b2ca33c..2cd2bf2d45 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java @@ -10,91 +10,83 @@ import java.util.Date; @Document(collection = "travel_deal") public class TravelDeal { - @Id - private BigInteger id; + @Id + private BigInteger id; - private String destination; + private String destination; - private String description; + private String description; - @Field("deal_price") - private double dealPrice; + @Field("deal_price") + private double dealPrice; - @Field("old_price") - private double oldPrice; + @Field("old_price") + private double oldPrice; - @Field("departure_date") - private Date departureDate; + @Field("departure_date") + private Date departureDate; - @Field("arrival_date") - private Date arrivalDate; + @Field("arrival_date") + private Date arrivalDate; - public BigInteger getId() { - return id; - } + public BigInteger getId() { + return id; + } - public void setId(BigInteger id) { - this.id = id; - } + public void setId(BigInteger id) { + this.id = id; + } - public String getDestination() { - return destination; - } + public String getDestination() { + return destination; + } - public void setDestination(String destination) { - this.destination = destination; - } + public void setDestination(String destination) { + this.destination = destination; + } - public String getDescription() { - return description; - } + public String getDescription() { + return description; + } - public void setDescription(String description) { - this.description = description; - } + public void setDescription(String description) { + this.description = description; + } - public double getDealPrice() { - return dealPrice; - } + public double getDealPrice() { + return dealPrice; + } - public void setDealPrice(double dealPrice) { - this.dealPrice = dealPrice; - } + public void setDealPrice(double dealPrice) { + this.dealPrice = dealPrice; + } - public double getOldPrice() { - return oldPrice; - } + public double getOldPrice() { + return oldPrice; + } - public void setOldPrice(double oldPrice) { - this.oldPrice = oldPrice; - } + public void setOldPrice(double oldPrice) { + this.oldPrice = oldPrice; + } - public Date getDepartureDate() { - return departureDate; - } + public Date getDepartureDate() { + return departureDate; + } - public void setDepartureDate(Date departureDate) { - this.departureDate = departureDate; - } + public void setDepartureDate(Date departureDate) { + this.departureDate = departureDate; + } - public Date getArrivalDate() { - return arrivalDate; - } + public Date getArrivalDate() { + return arrivalDate; + } - public void setArrivalDate(Date arrivalDate) { - this.arrivalDate = arrivalDate; - } + public void setArrivalDate(Date arrivalDate) { + this.arrivalDate = arrivalDate; + } - @Override - public String toString() { - return "TravelDeal{" + - "id=" + id + - ", destination='" + destination + '\'' + - ", description='" + description + '\'' + - ", dealPrice=" + dealPrice + - ", oldPrice=" + oldPrice + - ", departureDate=" + departureDate + - ", arrivalDate=" + arrivalDate + - '}'; - } + @Override + public String toString() { + return "TravelDeal{" + "id=" + id + ", destination='" + destination + '\'' + ", description='" + description + '\'' + ", dealPrice=" + dealPrice + ", oldPrice=" + oldPrice + ", departureDate=" + departureDate + ", arrivalDate=" + arrivalDate + '}'; + } } diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java index f7dc5a843e..20c1e3b67a 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java +++ b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java @@ -9,5 +9,4 @@ public interface TravelDealRepository extends MongoRepository findByDestination(String destination); - } \ No newline at end of file From f914b19bdbcfa5e4f2e3ddbd4e3bdefab7d94ec7 Mon Sep 17 00:00:00 2001 From: caroline Date: Mon, 18 Mar 2019 14:57:31 +0100 Subject: [PATCH 409/496] Formatting changes --- .../spring/cloud/kubernetes/client/TravelAgencyService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java index 9e59be4805..5ce6d7b8a1 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java @@ -14,8 +14,8 @@ public class TravelAgencyService { this.restTemplate = restTemplate; } - @HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = - { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") }) + @HystrixCommand(fallbackMethod = "getFallbackName", commandProperties = { + @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000") }) public String getDeals() { return this.restTemplate.getForObject("http://travel-agency-service:8080/deals", String.class); } From 8005f6b3131d62d222bf2b33ba3d19aac7c6e01e Mon Sep 17 00:00:00 2001 From: Urvy Agrawal Date: Mon, 18 Mar 2019 20:54:17 +0530 Subject: [PATCH 410/496] BAEL-2590 Added files for jlink tutorial (#6552) --- .../jlinkModule/com/baeldung/jlink/HelloWorld.java | 12 ++++++++++++ .../src/modules/jlinkModule/module-info.java | 3 +++ 2 files changed, 15 insertions(+) create mode 100644 core-java-11/src/modules/jlinkModule/com/baeldung/jlink/HelloWorld.java create mode 100644 core-java-11/src/modules/jlinkModule/module-info.java diff --git a/core-java-11/src/modules/jlinkModule/com/baeldung/jlink/HelloWorld.java b/core-java-11/src/modules/jlinkModule/com/baeldung/jlink/HelloWorld.java new file mode 100644 index 0000000000..47fe62ba40 --- /dev/null +++ b/core-java-11/src/modules/jlinkModule/com/baeldung/jlink/HelloWorld.java @@ -0,0 +1,12 @@ +package com.baeldung.jlink; + +import java.util.logging.Logger; + +public class HelloWorld { + + private static final Logger LOG = Logger.getLogger(HelloWorld.class.getName()); + + public static void main(String[] args) { + LOG.info("Hello World!"); + } +} diff --git a/core-java-11/src/modules/jlinkModule/module-info.java b/core-java-11/src/modules/jlinkModule/module-info.java new file mode 100644 index 0000000000..0587c65b53 --- /dev/null +++ b/core-java-11/src/modules/jlinkModule/module-info.java @@ -0,0 +1,3 @@ +module jlinkModule { + requires java.logging; +} \ No newline at end of file From 384dad60f19e5b4781d5ac64ac18db1a8a3c9801 Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Mon, 18 Mar 2019 20:19:37 +0000 Subject: [PATCH 411/496] BAEL-2522 Kevin comments addressed --- .../XmlGregorianCalendarConverterUnitTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java b/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java index 34510a3167..b221c04199 100644 --- a/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java +++ b/java-dates-2/src/test/java/com/baeldung/xmlgregoriancalendar/XmlGregorianCalendarConverterUnitTest.java @@ -3,6 +3,7 @@ package com.baeldung.xmlgregoriancalendar; import org.junit.Test; import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeConstants; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import java.time.LocalDate; @@ -19,6 +20,7 @@ public class XmlGregorianCalendarConverterUnitTest { assertThat(xmlGregorianCalendar.getYear()).isEqualTo(localDate.getYear()); assertThat(xmlGregorianCalendar.getMonth()).isEqualTo(localDate.getMonthValue()); assertThat(xmlGregorianCalendar.getDay()).isEqualTo(localDate.getDayOfMonth()); + assertThat(xmlGregorianCalendar.getTimezone()).isEqualTo(DatatypeConstants.FIELD_UNDEFINED); } @Test From 92b03457a154b749521e7f8a455924ae9b35bad8 Mon Sep 17 00:00:00 2001 From: juanvaccari Date: Mon, 18 Mar 2019 23:59:04 +0000 Subject: [PATCH 412/496] BAEL-2650 - Change scope functions tests to use assertTrue (#6558) * BAEL-2650 - Kotlin standard functions: run, with, let, also and apply * BAEL-2650 - Change scope functions tests to use assertTrue --- .../baeldung/scope/ScopeFunctionsUnitTest.kt | 46 ++++++++++++++----- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt index ef082655eb..cb3ed98006 100644 --- a/core-kotlin-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt @@ -1,7 +1,8 @@ package com.baeldung.scope -import org.assertj.core.api.Assertions.assertThat import org.junit.Test +import kotlin.test.assertTrue + class ScopeFunctionsUnitTest { @@ -24,7 +25,10 @@ class ScopeFunctionsUnitTest { it.append("It takes a StringBuilder instance and returns the number of characters in the generated String") it.length } - assertThat(numberOfCharacters).isEqualTo(128) + + assertTrue { + numberOfCharacters == 128 + } } @Test @@ -35,14 +39,18 @@ class ScopeFunctionsUnitTest { "At this point is safe to reference the variable. Let's print the message: $it" } ?: "default value" - assertThat(charactersInMessage).isEqualTo("At this point is safe to reference the variable. Let's print the message: hello there!") + assertTrue { + charactersInMessage.equals("At this point is safe to reference the variable. Let's print the message: hello there!") + } val aNullMessage = null val thisIsNull = aNullMessage?.let { "At this point it would be safe to reference the variable. But it will not really happen because it is null. Let's reference: $it" } ?: "default value" - assertThat(thisIsNull).isEqualTo("default value") + assertTrue { + thisIsNull.equals("default value") + } } @Test @@ -52,7 +60,10 @@ class ScopeFunctionsUnitTest { name = "Mary" surname = "Smith" } - assertThat(aStudent.name).isEqualTo("Mary") + + assertTrue { + aStudent.name.equals("Mary") + } } @Test @@ -62,7 +73,9 @@ class ScopeFunctionsUnitTest { .setName("Martha") .setSurname("Spector") - assertThat(teacher.surname).isEqualTo("Spector") + assertTrue { + teacher.surname.equals("Spector") + } } @Test @@ -76,14 +89,19 @@ class ScopeFunctionsUnitTest { .also { logger.info(it.toString()) } .headers - assertThat(logger.wasCalled()).isTrue() - assertThat(headers.headerInfo).isEqualTo("some header info") + assertTrue { + logger.wasCalled() && headers.headerInfo.equals("some header info") + } + } @Test fun shouldInitializeFieldWhenAlsoUsed() { val aStudent = Student().also { it.name = "John"} - assertThat(aStudent.name).isEqualTo("John") + + assertTrue { + aStudent.name.equals("John") + } } @Test @@ -104,7 +122,10 @@ class ScopeFunctionsUnitTest { append("It takes a StringBuilder instance and returns the number of characters in the generated String") length } - assertThat(numberOfCharacters).isEqualTo(128) + + assertTrue { + numberOfCharacters == 128 + } } @Test @@ -113,7 +134,10 @@ class ScopeFunctionsUnitTest { val charactersInMessage = message?.run { "At this point is safe to reference the variable. Let's print the message: $this" } ?: "default value" - assertThat(charactersInMessage).isEqualTo("At this point is safe to reference the variable. Let's print the message: hello there!") + + assertTrue { + charactersInMessage.equals("At this point is safe to reference the variable. Let's print the message: hello there!") + } } } \ No newline at end of file From aaddee0a7e81ff268746f67afd964152c2be1393 Mon Sep 17 00:00:00 2001 From: rahusriv Date: Tue, 19 Mar 2019 11:00:14 +0530 Subject: [PATCH 413/496] Rahul/socket/read/pr2 (#6398) * Making examples simple * Changing variable names * Modificatons in naming * Read all data from server * Adding seperate TestSocketRead class having live test * Adding test case * Changing test name to live tests --- .../java/com/baeldung/socket/read/Client.java | 37 ++++++++++++++ .../java/com/baeldung/socket/read/Server.java | 51 +++++++++++++++++++ .../read/SocketReadAllDataLiveTest.java | 37 ++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 core-java-networking/src/main/java/com/baeldung/socket/read/Client.java create mode 100644 core-java-networking/src/main/java/com/baeldung/socket/read/Server.java create mode 100644 core-java-networking/src/test/java/com/baeldung/socket/read/SocketReadAllDataLiveTest.java diff --git a/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java b/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java new file mode 100644 index 0000000000..08292237f2 --- /dev/null +++ b/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java @@ -0,0 +1,37 @@ +package com.baeldung.socket.read; + +import java.net.*; +import java.io.*; + +public class Client { + + //Initialize socket, input and output stream + private Socket socket = null; + private DataInputStream in = null; + private DataOutputStream out = null; + + public void runClient(String ip, int port) { + try { + socket = new Socket(ip, port); + System.out.println("Connected to server ..."); + in = new DataInputStream(System.in); + out = new DataOutputStream(socket.getOutputStream()); + } catch(Exception e) { + e.printStackTrace(); + } + char type = 's'; // s for string + int length = 29; + String data = "This is a string of length 29"; + byte[] dataInBytes = data.getBytes(); + //Sending data in TLV format + try { + out.writeChar(type); + out.writeInt(length); + out.write(dataInBytes); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java b/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java new file mode 100644 index 0000000000..bdb3a4449f --- /dev/null +++ b/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java @@ -0,0 +1,51 @@ +package com.baeldung.socket.read; + +import java.net.*; +import java.io.*; + +public class Server { + + //Socket and input stream + private Socket socket = null; + private ServerSocket server = null; + private DataInputStream in = null; + + public void runServer(int port) { + //Start the server and wait for connection + try { + server = new ServerSocket(port); + System.out.println("Server Started. Waiting for connection ..."); + socket = server.accept(); + System.out.println("Got connection from client."); + //Get input stream from socket variable and convert the same to DataInputStream + in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); + //Read type and length of data + char dataType = in.readChar(); + int length = in.readInt(); + System.out.println("Type : "+dataType); + System.out.println("Lenght :"+length); + //Read String data in bytes + byte[] messageByte = new byte[length]; + boolean end = false; + String dataString = ""; + int totalBytesRead = 0; + //We need to run while loop, to read all data in that stream + while(!end) { + int currentBytesRead = in.read(messageByte); + totalBytesRead = currentBytesRead + totalBytesRead; + if(totalBytesRead <= length) { + dataString += new String(messageByte,0,currentBytesRead); + } else { + dataString += new String(messageByte,0,length - totalBytesRead + currentBytesRead); + } + if(dataString.length()>=length) { + end = true; + } + } + System.out.println("Read "+length+" bytes of message from client. Message = "+dataString);; + } catch (Exception e) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/core-java-networking/src/test/java/com/baeldung/socket/read/SocketReadAllDataLiveTest.java b/core-java-networking/src/test/java/com/baeldung/socket/read/SocketReadAllDataLiveTest.java new file mode 100644 index 0000000000..da7f5b8d3f --- /dev/null +++ b/core-java-networking/src/test/java/com/baeldung/socket/read/SocketReadAllDataLiveTest.java @@ -0,0 +1,37 @@ +package com.baeldung.socket.read; + +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.Test; + +public class SocketReadAllDataLiveTest { + + @Test + public void givenServerAndClient_whenClientSendsAndServerReceivesData_thenCorrect() { + //Run server in new thread + Runnable runnable1 = () -> { runServer(); }; + Thread thread1 = new Thread(runnable1); + thread1.start(); + //Wait for 10 seconds + try { + TimeUnit.SECONDS.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + //Run client in a new thread + Runnable runnable2 = () -> { runClient(); }; + Thread thread2 = new Thread(runnable2); + thread2.start(); + } + + public static void runServer() { + //Run Server + Server server = new Server(); + server.runServer(5555); + } + + public static void runClient() { + //Run Client + Client client = new Client(); + client.runClient("127.0.0.1", 5555); + } +} \ No newline at end of file From a03ec155b4231e1bb369baa194a63b5d40484cb9 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 19 Mar 2019 06:31:54 -0600 Subject: [PATCH 414/496] Initial application generated by JHipster-5.8.2 --- jhipster-5/bookstore-monolith/.editorconfig | 24 + jhipster-5/bookstore-monolith/.gitattributes | 148 + jhipster-5/bookstore-monolith/.gitignore | 145 + jhipster-5/bookstore-monolith/.huskyrc | 5 + .../.mvn/wrapper/MavenWrapperDownloader.java | 110 + .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 48337 bytes .../.mvn/wrapper/maven-wrapper.properties | 1 + jhipster-5/bookstore-monolith/.prettierignore | 3 + jhipster-5/bookstore-monolith/.prettierrc | 12 + jhipster-5/bookstore-monolith/.yo-rc.json | 34 + jhipster-5/bookstore-monolith/README.md | 179 + jhipster-5/bookstore-monolith/angular.json | 39 + jhipster-5/bookstore-monolith/mvnw | 286 + jhipster-5/bookstore-monolith/mvnw.cmd | 161 + .../bookstore-monolith/package-lock.json | 18244 ++++++++++++++++ jhipster-5/bookstore-monolith/package.json | 128 + jhipster-5/bookstore-monolith/pom.xml | 1085 + .../bookstore-monolith/postcss.config.js | 5 + jhipster-5/bookstore-monolith/proxy.conf.json | 7 + .../src/main/docker/.dockerignore | 14 + .../src/main/docker/Dockerfile | 20 + .../src/main/docker/app.yml | 15 + .../src/main/docker/entrypoint.sh | 4 + .../src/main/docker/mysql.yml | 13 + .../src/main/docker/sonar.yml | 7 + .../baeldung/jhipster5/ApplicationWebXml.java | 21 + .../com/baeldung/jhipster5/BookstoreApp.java | 98 + .../jhipster5/aop/logging/LoggingAspect.java | 98 + .../config/ApplicationProperties.java | 14 + .../jhipster5/config/AsyncConfiguration.java | 59 + .../config/CloudDatabaseConfiguration.java | 28 + .../baeldung/jhipster5/config/Constants.java | 17 + .../config/DatabaseConfiguration.java | 59 + .../config/DateTimeFormatConfiguration.java | 20 + .../jhipster5/config/DefaultProfileUtil.java | 51 + .../config/JacksonConfiguration.java | 63 + .../config/LiquibaseConfiguration.java | 50 + .../jhipster5/config/LocaleConfiguration.java | 27 + .../config/LoggingAspectConfiguration.java | 19 + .../config/LoggingConfiguration.java | 154 + .../config/SecurityConfiguration.java | 121 + .../jhipster5/config/WebConfigurer.java | 170 + .../config/audit/AuditEventConverter.java | 86 + .../jhipster5/config/audit/package-info.java | 4 + .../jhipster5/config/package-info.java | 4 + .../domain/AbstractAuditingEntity.java | 79 + .../baeldung/jhipster5/domain/Authority.java | 59 + .../domain/PersistentAuditEvent.java | 109 + .../com/baeldung/jhipster5/domain/User.java | 231 + .../jhipster5/domain/package-info.java | 4 + .../repository/AuthorityRepository.java | 11 + .../CustomAuditEventRepository.java | 89 + .../PersistenceAuditEventRepository.java | 25 + .../jhipster5/repository/UserRepository.java | 40 + .../jhipster5/repository/package-info.java | 4 + .../security/AuthoritiesConstants.java | 16 + .../security/DomainUserDetailsService.java | 62 + .../jhipster5/security/SecurityUtils.java | 76 + .../security/SpringSecurityAuditorAware.java | 20 + .../security/UserNotActivatedException.java | 19 + .../jhipster5/security/jwt/JWTConfigurer.java | 21 + .../jhipster5/security/jwt/JWTFilter.java | 48 + .../jhipster5/security/jwt/TokenProvider.java | 119 + .../jhipster5/security/package-info.java | 4 + .../jhipster5/service/AuditEventService.java | 51 + .../jhipster5/service/MailService.java | 105 + .../jhipster5/service/UserService.java | 273 + .../service/dto/PasswordChangeDTO.java | 35 + .../jhipster5/service/dto/UserDTO.java | 199 + .../jhipster5/service/dto/package-info.java | 4 + .../jhipster5/service/mapper/UserMapper.java | 81 + .../service/mapper/package-info.java | 4 + .../jhipster5/service/package-info.java | 4 + .../jhipster5/service/util/RandomUtil.java | 41 + .../jhipster5/web/rest/AccountResource.java | 179 + .../jhipster5/web/rest/AuditResource.java | 77 + .../jhipster5/web/rest/LogsResource.java | 36 + .../jhipster5/web/rest/UserJWTController.java | 71 + .../jhipster5/web/rest/UserResource.java | 183 + .../rest/errors/BadRequestAlertException.java | 42 + .../errors/CustomParameterizedException.java | 54 + .../errors/EmailAlreadyUsedException.java | 10 + .../rest/errors/EmailNotFoundException.java | 13 + .../web/rest/errors/ErrorConstants.java | 21 + .../web/rest/errors/ExceptionTranslator.java | 112 + .../web/rest/errors/FieldErrorVM.java | 33 + .../errors/InternalServerErrorException.java | 16 + .../rest/errors/InvalidPasswordException.java | 13 + .../errors/LoginAlreadyUsedException.java | 10 + .../web/rest/errors/package-info.java | 6 + .../jhipster5/web/rest/package-info.java | 4 + .../jhipster5/web/rest/util/HeaderUtil.java | 45 + .../web/rest/util/PaginationUtil.java | 45 + .../web/rest/vm/KeyAndPasswordVM.java | 27 + .../jhipster5/web/rest/vm/LoggerVM.java | 46 + .../jhipster5/web/rest/vm/LoginVM.java | 52 + .../jhipster5/web/rest/vm/ManagedUserVM.java | 35 + .../jhipster5/web/rest/vm/package-info.java | 4 + .../src/main/jib/entrypoint.sh | 4 + .../src/main/resources/.h2.server.properties | 5 + .../src/main/resources/banner.txt | 10 + .../main/resources/config/application-dev.yml | 122 + .../resources/config/application-prod.yml | 133 + .../main/resources/config/application-tls.yml | 20 + .../src/main/resources/config/application.yml | 140 + .../config/liquibase/authorities.csv | 3 + .../00000000000000_initial_schema.xml | 152 + .../resources/config/liquibase/master.xml | 10 + .../main/resources/config/liquibase/users.csv | 5 + .../config/liquibase/users_authorities.csv | 6 + .../main/resources/config/tls/keystore.p12 | Bin 0 -> 2607 bytes .../main/resources/i18n/messages.properties | 21 + .../src/main/resources/logback-spring.xml | 66 + .../src/main/resources/templates/error.html | 163 + .../templates/mail/activationEmail.html | 25 + .../templates/mail/creationEmail.html | 25 + .../templates/mail/passwordResetEmail.html | 25 + .../src/main/webapp/404.html | 61 + .../main/webapp/app/account/account.module.ts | 30 + .../main/webapp/app/account/account.route.ts | 12 + .../account/activate/activate.component.html | 17 + .../account/activate/activate.component.ts | 37 + .../app/account/activate/activate.route.ts | 12 + .../app/account/activate/activate.service.ts | 16 + .../src/main/webapp/app/account/index.ts | 19 + .../password-reset-finish.component.html | 77 + .../finish/password-reset-finish.component.ts | 65 + .../finish/password-reset-finish.route.ts | 12 + .../finish/password-reset-finish.service.ts | 14 + .../init/password-reset-init.component.html | 46 + .../init/password-reset-init.component.ts | 43 + .../init/password-reset-init.route.ts | 12 + .../init/password-reset-init.service.ts | 14 + .../password-strength-bar.component.ts | 85 + .../password/password-strength-bar.scss | 23 + .../account/password/password.component.html | 77 + .../account/password/password.component.ts | 46 + .../app/account/password/password.route.ts | 14 + .../app/account/password/password.service.ts | 14 + .../account/register/register.component.html | 124 + .../account/register/register.component.ts | 71 + .../app/account/register/register.route.ts | 12 + .../app/account/register/register.service.ts | 14 + .../account/settings/settings.component.html | 80 + .../account/settings/settings.component.ts | 50 + .../app/account/settings/settings.route.ts | 14 + .../src/main/webapp/app/admin/admin.module.ts | 43 + .../src/main/webapp/app/admin/admin.route.ts | 18 + .../app/admin/audits/audit-data.model.ts | 3 + .../webapp/app/admin/audits/audit.model.ts | 5 + .../app/admin/audits/audits.component.html | 52 + .../app/admin/audits/audits.component.ts | 126 + .../webapp/app/admin/audits/audits.route.ts | 17 + .../webapp/app/admin/audits/audits.service.ts | 25 + .../configuration.component.html | 46 + .../configuration/configuration.component.ts | 43 + .../configuration/configuration.route.ts | 11 + .../configuration/configuration.service.ts | 67 + .../webapp/app/admin/docs/docs.component.html | 2 + .../webapp/app/admin/docs/docs.component.ts | 9 + .../main/webapp/app/admin/docs/docs.route.ts | 11 + .../admin/health/health-modal.component.html | 35 + .../admin/health/health-modal.component.ts | 41 + .../app/admin/health/health.component.html | 34 + .../app/admin/health/health.component.ts | 66 + .../webapp/app/admin/health/health.route.ts | 11 + .../webapp/app/admin/health/health.service.ts | 133 + .../src/main/webapp/app/admin/index.ts | 27 + .../main/webapp/app/admin/logs/log.model.ts | 3 + .../webapp/app/admin/logs/logs.component.html | 28 + .../webapp/app/admin/logs/logs.component.ts | 32 + .../main/webapp/app/admin/logs/logs.route.ts | 11 + .../webapp/app/admin/logs/logs.service.ts | 19 + .../app/admin/metrics/metrics.component.html | 56 + .../app/admin/metrics/metrics.component.ts | 42 + .../webapp/app/admin/metrics/metrics.route.ts | 11 + .../app/admin/metrics/metrics.service.ts | 18 + ...er-management-delete-dialog.component.html | 19 + ...user-management-delete-dialog.component.ts | 29 + .../user-management-detail.component.html | 47 + .../user-management-detail.component.ts | 20 + .../user-management-update.component.html | 118 + .../user-management-update.component.ts | 51 + .../user-management.component.html | 78 + .../user-management.component.ts | 144 + .../user-management/user-management.route.ts | 68 + .../src/main/webapp/app/app-routing.module.ts | 23 + .../src/main/webapp/app/app.constants.ts | 8 + .../src/main/webapp/app/app.main.ts | 14 + .../src/main/webapp/app/app.module.ts | 70 + .../webapp/app/blocks/config/prod.config.ts | 9 + .../blocks/config/uib-pagination.config.ts | 14 + .../interceptor/auth-expired.interceptor.ts | 25 + .../blocks/interceptor/auth.interceptor.ts | 27 + .../interceptor/errorhandler.interceptor.ts | 25 + .../interceptor/notification.interceptor.ts | 34 + .../webapp/app/core/auth/account.service.ts | 108 + .../webapp/app/core/auth/auth-jwt.service.ts | 59 + .../main/webapp/app/core/auth/csrf.service.ts | 11 + .../app/core/auth/state-storage.service.ts | 46 + .../core/auth/user-route-access-service.ts | 52 + .../src/main/webapp/app/core/core.module.ts | 24 + .../src/main/webapp/app/core/index.ts | 11 + .../app/core/login/login-modal.service.ts | 27 + .../webapp/app/core/login/login.service.ts | 38 + .../webapp/app/core/user/account.model.ts | 12 + .../main/webapp/app/core/user/user.model.ts | 47 + .../main/webapp/app/core/user/user.service.ts | 39 + .../main/webapp/app/entities/entity.module.ts | 15 + .../main/webapp/app/home/home.component.html | 41 + .../main/webapp/app/home/home.component.ts | 44 + .../src/main/webapp/app/home/home.module.ts | 12 + .../src/main/webapp/app/home/home.route.ts | 12 + .../src/main/webapp/app/home/home.scss | 23 + .../src/main/webapp/app/home/index.ts | 3 + .../app/layouts/error/error.component.html | 19 + .../app/layouts/error/error.component.ts | 28 + .../webapp/app/layouts/error/error.route.ts | 36 + .../app/layouts/footer/footer.component.html | 3 + .../app/layouts/footer/footer.component.ts | 7 + .../src/main/webapp/app/layouts/index.ts | 9 + .../app/layouts/main/main.component.html | 11 + .../webapp/app/layouts/main/main.component.ts | 31 + .../app/layouts/navbar/navbar.component.html | 139 + .../app/layouts/navbar/navbar.component.ts | 65 + .../webapp/app/layouts/navbar/navbar.route.ts | 9 + .../webapp/app/layouts/navbar/navbar.scss | 53 + .../layouts/profiles/page-ribbon.component.ts | 26 + .../app/layouts/profiles/page-ribbon.scss | 31 + .../layouts/profiles/profile-info.model.ts | 6 + .../app/layouts/profiles/profile.service.ts | 40 + .../src/main/webapp/app/polyfills.ts | 70 + .../app/shared/alert/alert-error.component.ts | 110 + .../app/shared/alert/alert.component.ts | 35 + .../auth/has-any-authority.directive.ts | 42 + .../app/shared/constants/error.constants.ts | 4 + .../app/shared/constants/input.constants.ts | 2 + .../shared/constants/pagination.constants.ts | 1 + .../src/main/webapp/app/shared/index.ts | 12 + .../app/shared/login/login.component.html | 43 + .../app/shared/login/login.component.ts | 87 + .../webapp/app/shared/shared-common.module.ts | 10 + .../webapp/app/shared/shared-libs.module.ts | 20 + .../main/webapp/app/shared/shared.module.ts | 21 + .../app/shared/util/datepicker-adapter.ts | 21 + .../webapp/app/shared/util/request-util.ts | 18 + .../src/main/webapp/app/vendor.ts | 81 + .../src/main/webapp/content/css/loading.css | 152 + .../images/jhipster_family_member_0.svg | 198 + .../jhipster_family_member_0_head-192.png | Bin 0 -> 13322 bytes .../jhipster_family_member_0_head-256.png | Bin 0 -> 17812 bytes .../jhipster_family_member_0_head-384.png | Bin 0 -> 27723 bytes .../jhipster_family_member_0_head-512.png | Bin 0 -> 37449 bytes .../images/jhipster_family_member_1.svg | 9387 ++++++++ .../jhipster_family_member_1_head-192.png | Bin 0 -> 19660 bytes .../jhipster_family_member_1_head-256.png | Bin 0 -> 29152 bytes .../jhipster_family_member_1_head-384.png | Bin 0 -> 48895 bytes .../jhipster_family_member_1_head-512.png | Bin 0 -> 68803 bytes .../images/jhipster_family_member_2.svg | 841 + .../jhipster_family_member_2_head-192.png | Bin 0 -> 11463 bytes .../jhipster_family_member_2_head-256.png | Bin 0 -> 15638 bytes .../jhipster_family_member_2_head-384.png | Bin 0 -> 23850 bytes .../jhipster_family_member_2_head-512.png | Bin 0 -> 32300 bytes .../images/jhipster_family_member_3.svg | 308 + .../jhipster_family_member_3_head-192.png | Bin 0 -> 13573 bytes .../jhipster_family_member_3_head-256.png | Bin 0 -> 19239 bytes .../jhipster_family_member_3_head-384.png | Bin 0 -> 30253 bytes .../jhipster_family_member_3_head-512.png | Bin 0 -> 41857 bytes .../webapp/content/images/logo-jhipster.png | Bin 0 -> 1085 bytes .../content/scss/_bootstrap-variables.scss | 42 + .../src/main/webapp/content/scss/global.scss | 226 + .../src/main/webapp/content/scss/vendor.scss | 12 + .../src/main/webapp/favicon.ico | Bin 0 -> 1574 bytes .../src/main/webapp/index.html | 108 + .../src/main/webapp/manifest.webapp | 31 + .../src/main/webapp/robots.txt | 11 + .../src/main/webapp/swagger-ui/index.html | 166 + .../jhipster5/config/WebConfigurerTest.java | 189 + .../config/WebConfigurerTestController.java | 16 + .../timezone/HibernateTimeZoneTest.java | 176 + .../CustomAuditEventRepositoryIntTest.java | 165 + .../repository/timezone/DateTimeWrapper.java | 131 + .../timezone/DateTimeWrapperRepository.java | 12 + .../DomainUserDetailsServiceIntTest.java | 127 + .../security/SecurityUtilsUnitTest.java | 73 + .../jhipster5/security/jwt/JWTFilterTest.java | 115 + .../security/jwt/TokenProviderTest.java | 111 + .../jhipster5/service/MailServiceIntTest.java | 187 + .../jhipster5/service/UserServiceIntTest.java | 192 + .../service/mapper/UserMapperTest.java | 150 + .../web/rest/AccountResourceIntTest.java | 818 + .../web/rest/AuditResourceIntTest.java | 162 + .../web/rest/LogsResourceIntTest.java | 66 + .../baeldung/jhipster5/web/rest/TestUtil.java | 141 + .../web/rest/UserJWTControllerIntTest.java | 125 + .../web/rest/UserResourceIntTest.java | 596 + .../errors/ExceptionTranslatorIntTest.java | 150 + .../ExceptionTranslatorTestController.java | 86 + .../web/rest/util/PaginationUtilUnitTest.java | 44 + .../src/test/javascript/jest-global-mocks.ts | 15 + .../src/test/javascript/jest.conf.js | 26 + .../src/test/javascript/jest.ts | 2 + .../activate/activate.component.spec.ts | 72 + .../password-reset-finish.component.spec.ts | 119 + .../password-reset-init.component.spec.ts | 110 + .../password-strength-bar.component.spec.ts | 48 + .../password/password.component.spec.ts | 89 + .../register/register.component.spec.ts | 118 + .../settings/settings.component.spec.ts | 81 + .../app/admin/audits/audits.component.spec.ts | 133 + .../app/admin/audits/audits.service.spec.ts | 59 + .../configuration.component.spec.ts | 71 + .../configuration.service.spec.ts | 64 + .../app/admin/health/health.component.spec.ts | 321 + .../app/admin/logs/logs.component.spec.ts | 77 + .../spec/app/admin/logs/logs.service.spec.ts | 58 + .../admin/metrics/metrics.component.spec.ts | 55 + .../app/admin/metrics/metrics.service.spec.ts | 57 + ...management-delete-dialog.component.spec.ts | 54 + .../user-management-detail.component.spec.ts | 65 + .../user-management-update.component.spec.ts | 99 + .../user-management.component.spec.ts | 85 + .../app/core/user/account.service.spec.ts | 102 + .../spec/app/core/user/user.service.spec.ts | 66 + .../alert/alert-error.component.spec.ts | 134 + .../app/shared/login/login.component.spec.ts | 157 + .../spec/helpers/mock-account.service.ts | 35 + .../spec/helpers/mock-active-modal.service.ts | 12 + .../spec/helpers/mock-alert.service.ts | 11 + .../helpers/mock-event-manager.service.ts | 12 + .../spec/helpers/mock-login.service.ts | 29 + .../spec/helpers/mock-route.service.ts | 29 + .../helpers/mock-state-storage.service.ts | 22 + .../test/javascript/spec/helpers/spyobject.ts | 69 + .../src/test/javascript/spec/test.module.ts | 63 + .../src/test/resources/config/application.yml | 105 + .../resources/i18n/messages_en.properties | 1 + .../src/test/resources/logback.xml | 42 + .../resources/templates/mail/testEmail.html | 1 + .../bookstore-monolith/tsconfig-aot.json | 28 + jhipster-5/bookstore-monolith/tsconfig.json | 25 + jhipster-5/bookstore-monolith/tslint.json | 76 + .../webpack/logo-jhipster.png | Bin 0 -> 4459 bytes .../bookstore-monolith/webpack/utils.js | 44 + .../webpack/webpack.common.js | 86 + .../bookstore-monolith/webpack/webpack.dev.js | 148 + .../webpack/webpack.prod.js | 144 + 347 files changed, 49080 insertions(+) create mode 100644 jhipster-5/bookstore-monolith/.editorconfig create mode 100644 jhipster-5/bookstore-monolith/.gitattributes create mode 100644 jhipster-5/bookstore-monolith/.gitignore create mode 100644 jhipster-5/bookstore-monolith/.huskyrc create mode 100644 jhipster-5/bookstore-monolith/.mvn/wrapper/MavenWrapperDownloader.java create mode 100644 jhipster-5/bookstore-monolith/.mvn/wrapper/maven-wrapper.jar create mode 100644 jhipster-5/bookstore-monolith/.mvn/wrapper/maven-wrapper.properties create mode 100644 jhipster-5/bookstore-monolith/.prettierignore create mode 100644 jhipster-5/bookstore-monolith/.prettierrc create mode 100644 jhipster-5/bookstore-monolith/.yo-rc.json create mode 100644 jhipster-5/bookstore-monolith/README.md create mode 100644 jhipster-5/bookstore-monolith/angular.json create mode 100755 jhipster-5/bookstore-monolith/mvnw create mode 100644 jhipster-5/bookstore-monolith/mvnw.cmd create mode 100644 jhipster-5/bookstore-monolith/package-lock.json create mode 100644 jhipster-5/bookstore-monolith/package.json create mode 100644 jhipster-5/bookstore-monolith/pom.xml create mode 100644 jhipster-5/bookstore-monolith/postcss.config.js create mode 100644 jhipster-5/bookstore-monolith/proxy.conf.json create mode 100644 jhipster-5/bookstore-monolith/src/main/docker/.dockerignore create mode 100644 jhipster-5/bookstore-monolith/src/main/docker/Dockerfile create mode 100644 jhipster-5/bookstore-monolith/src/main/docker/app.yml create mode 100644 jhipster-5/bookstore-monolith/src/main/docker/entrypoint.sh create mode 100644 jhipster-5/bookstore-monolith/src/main/docker/mysql.yml create mode 100644 jhipster-5/bookstore-monolith/src/main/docker/sonar.yml create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/ApplicationWebXml.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/BookstoreApp.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/aop/logging/LoggingAspect.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/ApplicationProperties.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/AsyncConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/CloudDatabaseConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/Constants.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DatabaseConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DateTimeFormatConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DefaultProfileUtil.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/JacksonConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LiquibaseConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LocaleConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LoggingAspectConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LoggingConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/SecurityConfiguration.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/WebConfigurer.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/audit/AuditEventConverter.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/audit/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/AbstractAuditingEntity.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/Authority.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/PersistentAuditEvent.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/User.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/AuthorityRepository.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/CustomAuditEventRepository.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/PersistenceAuditEventRepository.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/UserRepository.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/AuthoritiesConstants.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/DomainUserDetailsService.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/SecurityUtils.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/SpringSecurityAuditorAware.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/UserNotActivatedException.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/JWTConfigurer.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/JWTFilter.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/TokenProvider.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/AuditEventService.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/MailService.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/UserService.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/PasswordChangeDTO.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/UserDTO.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/UserMapper.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/util/RandomUtil.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/AccountResource.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/AuditResource.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/LogsResource.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/UserJWTController.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/UserResource.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/BadRequestAlertException.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/CustomParameterizedException.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/EmailAlreadyUsedException.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/EmailNotFoundException.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/ErrorConstants.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslator.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/FieldErrorVM.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/InternalServerErrorException.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/InvalidPasswordException.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/LoginAlreadyUsedException.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/util/HeaderUtil.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/util/PaginationUtil.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/KeyAndPasswordVM.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/LoggerVM.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/LoginVM.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/ManagedUserVM.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/package-info.java create mode 100644 jhipster-5/bookstore-monolith/src/main/jib/entrypoint.sh create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/.h2.server.properties create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/banner.txt create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/application-dev.yml create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/application-prod.yml create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/application-tls.yml create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/application.yml create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/authorities.csv create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/master.xml create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/users.csv create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/users_authorities.csv create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/tls/keystore.p12 create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/i18n/messages.properties create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/logback-spring.xml create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/templates/error.html create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/templates/mail/activationEmail.html create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/templates/mail/creationEmail.html create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/templates/mail/passwordResetEmail.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/404.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/account.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/account.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/index.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password-strength-bar.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password-strength-bar.scss create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/admin.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/admin.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audit-data.model.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audit.model.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health-modal.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health-modal.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/index.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/log.model.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-detail.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-detail.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-update.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-update.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/app-routing.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/app.constants.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/app.main.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/app.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/config/prod.config.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/config/uib-pagination.config.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/auth-expired.interceptor.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/auth.interceptor.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/errorhandler.interceptor.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/notification.interceptor.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/account.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/auth-jwt.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/csrf.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/state-storage.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/user-route-access-service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/core.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/index.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/login/login-modal.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/login/login.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/account.model.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/user.model.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/user.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/entity.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.scss create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/home/index.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/footer/footer.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/footer/footer.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/index.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/main/main.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/main/main.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.scss create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/page-ribbon.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/page-ribbon.scss create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/profile-info.model.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/profile.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/polyfills.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/alert/alert-error.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/alert/alert.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/auth/has-any-authority.directive.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/error.constants.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/input.constants.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/pagination.constants.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/index.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/login/login.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/login/login.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared-common.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared-libs.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/util/datepicker-adapter.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/util/request-util.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/vendor.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/css/loading.css create mode 100755 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0.svg create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-192.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-256.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-384.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-512.png create mode 100755 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1.svg create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-192.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-256.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-384.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-512.png create mode 100755 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2.svg create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-192.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-256.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-384.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-512.png create mode 100755 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3.svg create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-192.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-256.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-384.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-512.png create mode 100755 jhipster-5/bookstore-monolith/src/main/webapp/content/images/logo-jhipster.png create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/scss/_bootstrap-variables.scss create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/scss/global.scss create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/content/scss/vendor.scss create mode 100755 jhipster-5/bookstore-monolith/src/main/webapp/favicon.ico create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/index.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/manifest.webapp create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/robots.txt create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/swagger-ui/index.html create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/WebConfigurerTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/WebConfigurerTestController.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/timezone/HibernateTimeZoneTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/CustomAuditEventRepositoryIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/timezone/DateTimeWrapper.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/timezone/DateTimeWrapperRepository.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/DomainUserDetailsServiceIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/SecurityUtilsUnitTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/jwt/JWTFilterTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/jwt/TokenProviderTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/MailServiceIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/UserServiceIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/AccountResourceIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/AuditResourceIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/LogsResourceIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/TestUtil.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/UserJWTControllerIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/UserResourceIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslatorIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslatorTestController.java create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/util/PaginationUtilUnitTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/jest-global-mocks.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/jest.conf.js create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/jest.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/activate/activate.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password-reset/finish/password-reset-finish.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password-reset/init/password-reset-init.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password/password-strength-bar.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password/password.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/register/register.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/settings/settings.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/audits/audits.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/audits/audits.service.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/configuration/configuration.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/configuration/configuration.service.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/health/health.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/logs/logs.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/logs/logs.service.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/metrics/metrics.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/metrics/metrics.service.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-delete-dialog.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-detail.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-update.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/core/user/account.service.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/core/user/user.service.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/shared/alert/alert-error.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/shared/login/login.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-account.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-active-modal.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-alert.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-event-manager.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-login.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-route.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-state-storage.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/spyobject.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/test.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/resources/config/application.yml create mode 100644 jhipster-5/bookstore-monolith/src/test/resources/i18n/messages_en.properties create mode 100644 jhipster-5/bookstore-monolith/src/test/resources/logback.xml create mode 100644 jhipster-5/bookstore-monolith/src/test/resources/templates/mail/testEmail.html create mode 100644 jhipster-5/bookstore-monolith/tsconfig-aot.json create mode 100644 jhipster-5/bookstore-monolith/tsconfig.json create mode 100644 jhipster-5/bookstore-monolith/tslint.json create mode 100644 jhipster-5/bookstore-monolith/webpack/logo-jhipster.png create mode 100644 jhipster-5/bookstore-monolith/webpack/utils.js create mode 100644 jhipster-5/bookstore-monolith/webpack/webpack.common.js create mode 100644 jhipster-5/bookstore-monolith/webpack/webpack.dev.js create mode 100644 jhipster-5/bookstore-monolith/webpack/webpack.prod.js diff --git a/jhipster-5/bookstore-monolith/.editorconfig b/jhipster-5/bookstore-monolith/.editorconfig new file mode 100644 index 0000000000..a79c052f53 --- /dev/null +++ b/jhipster-5/bookstore-monolith/.editorconfig @@ -0,0 +1,24 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] + +# Change these settings to your own preference +indent_style = space +indent_size = 4 + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[package.json] +indent_style = space +indent_size = 2 diff --git a/jhipster-5/bookstore-monolith/.gitattributes b/jhipster-5/bookstore-monolith/.gitattributes new file mode 100644 index 0000000000..c013844d10 --- /dev/null +++ b/jhipster-5/bookstore-monolith/.gitattributes @@ -0,0 +1,148 @@ +# This file is inspired by https://github.com/alexkaratarakis/gitattributes +# +# Auto detect text files and perform LF normalization +# http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/ +* text=auto + +# The above will handle all files NOT found below +# These files are text and should be normalized (Convert crlf => lf) + +*.bat text eol=crlf +*.coffee text +*.css text +*.cql text +*.df text +*.ejs text +*.html text +*.java text +*.js text +*.json text +*.less text +*.properties text +*.sass text +*.scss text +*.sh text eol=lf +*.sql text +*.txt text +*.ts text +*.xml text +*.yaml text +*.yml text + +# Documents +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain +*.markdown text +*.md text +*.adoc text +*.textile text +*.mustache text +*.csv text +*.tab text +*.tsv text +*.txt text +AUTHORS text +CHANGELOG text +CHANGES text +CONTRIBUTING text +COPYING text +copyright text +*COPYRIGHT* text +INSTALL text +license text +LICENSE text +NEWS text +readme text +*README* text +TODO text + +# Graphics +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.tif binary +*.tiff binary +*.ico binary +# SVG treated as an asset (binary) by default. If you want to treat it as text, +# comment-out the following line and uncomment the line after. +*.svg binary +#*.svg text +*.eps binary + +# These files are binary and should be left untouched +# (binary is a macro for -text -diff) +*.class binary +*.jar binary +*.war binary + +## LINTERS +.csslintrc text +.eslintrc text +.jscsrc text +.jshintrc text +.jshintignore text +.stylelintrc text + +## CONFIGS +*.conf text +*.config text +.editorconfig text +.gitattributes text +.gitconfig text +.gitignore text +.htaccess text +*.npmignore text + +## HEROKU +Procfile text +.slugignore text + +## AUDIO +*.kar binary +*.m4a binary +*.mid binary +*.midi binary +*.mp3 binary +*.ogg binary +*.ra binary + +## VIDEO +*.3gpp binary +*.3gp binary +*.as binary +*.asf binary +*.asx binary +*.fla binary +*.flv binary +*.m4v binary +*.mng binary +*.mov binary +*.mp4 binary +*.mpeg binary +*.mpg binary +*.swc binary +*.swf binary +*.webm binary + +## ARCHIVES +*.7z binary +*.gz binary +*.rar binary +*.tar binary +*.zip binary + +## FONTS +*.ttf binary +*.eot binary +*.otf binary +*.woff binary +*.woff2 binary diff --git a/jhipster-5/bookstore-monolith/.gitignore b/jhipster-5/bookstore-monolith/.gitignore new file mode 100644 index 0000000000..f1f6845d33 --- /dev/null +++ b/jhipster-5/bookstore-monolith/.gitignore @@ -0,0 +1,145 @@ +###################### +# Project Specific +###################### +/src/main/webapp/content/css/main.css +/target/www/** +/src/test/javascript/coverage/ + +###################### +# Node +###################### +/node/ +node_tmp/ +node_modules/ +npm-debug.log.* +/.awcache/* +/.cache-loader/* + +###################### +# SASS +###################### +.sass-cache/ + +###################### +# Eclipse +###################### +*.pydevproject +.project +.metadata +tmp/ +tmp/**/* +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath +.factorypath +/src/main/resources/rebel.xml + +# External tool builders +.externalToolBuilders/** + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + +###################### +# Intellij +###################### +.idea/ +*.iml +*.iws +*.ipr +*.ids +*.orig +classes/ +out/ + +###################### +# Visual Studio Code +###################### +.vscode/ + +###################### +# Maven +###################### +/log/ +/target/ + +###################### +# Gradle +###################### +.gradle/ +/build/ + +###################### +# Package Files +###################### +*.jar +*.war +*.ear +*.db + +###################### +# Windows +###################### +# Windows image file caches +Thumbs.db + +# Folder config file +Desktop.ini + +###################### +# Mac OSX +###################### +.DS_Store +.svn + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +###################### +# Directories +###################### +/bin/ +/deploy/ + +###################### +# Logs +###################### +*.log* + +###################### +# Others +###################### +*.class +*.*~ +*~ +.merge_file* + +###################### +# Gradle Wrapper +###################### +!gradle/wrapper/gradle-wrapper.jar + +###################### +# Maven Wrapper +###################### +!.mvn/wrapper/maven-wrapper.jar + +###################### +# ESLint +###################### +.eslintcache diff --git a/jhipster-5/bookstore-monolith/.huskyrc b/jhipster-5/bookstore-monolith/.huskyrc new file mode 100644 index 0000000000..9e18d87674 --- /dev/null +++ b/jhipster-5/bookstore-monolith/.huskyrc @@ -0,0 +1,5 @@ +{ + "hooks": { + "pre-commit": "lint-staged" + } +} diff --git a/jhipster-5/bookstore-monolith/.mvn/wrapper/MavenWrapperDownloader.java b/jhipster-5/bookstore-monolith/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000..8fe1fab5a2 --- /dev/null +++ b/jhipster-5/bookstore-monolith/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,110 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = + "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if (mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if (mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: : " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if (!outputFile.getParentFile().exists()) { + if (!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/jhipster-5/bookstore-monolith/.mvn/wrapper/maven-wrapper.jar b/jhipster-5/bookstore-monolith/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..01e67997377a393fd672c7dcde9dccbedf0cb1e9 GIT binary patch literal 48337 zcmbTe1CV9Qwl>;j+wQV$+qSXFw%KK)%eHN!%U!l@+x~l>b1vR}@9y}|TM-#CBjy|< zb7YRpp)Z$$Gzci_H%LgxZ{NNV{%Qa9gZlF*E2<($D=8;N5Asbx8se{Sz5)O13x)rc z5cR(k$_mO!iis+#(8-D=#R@|AF(8UQ`L7dVNSKQ%v^P|1A%aF~Lye$@HcO@sMYOb3 zl`5!ThJ1xSJwsg7hVYFtE5vS^5UE0$iDGCS{}RO;R#3y#{w-1hVSg*f1)7^vfkxrm!!N|oTR0Hj?N~IbVk+yC#NK} z5myv()UMzV^!zkX@O=Yf!(Z_bF7}W>k*U4@--&RH0tHiHY0IpeezqrF#@8{E$9d=- z7^kT=1Bl;(Q0k{*_vzz1Et{+*lbz%mkIOw(UA8)EE-Pkp{JtJhe@VXQ8sPNTn$Vkj zicVp)sV%0omhsj;NCmI0l8zzAipDV#tp(Jr7p_BlL$}Pys_SoljztS%G-Wg+t z&Q#=<03Hoga0R1&L!B);r{Cf~b$G5p#@?R-NNXMS8@cTWE^7V!?ixz(Ag>lld;>COenWc$RZ61W+pOW0wh>sN{~j; zCBj!2nn|4~COwSgXHFH?BDr8pK323zvmDK-84ESq25b;Tg%9(%NneBcs3;r znZpzntG%E^XsSh|md^r-k0Oen5qE@awGLfpg;8P@a-s<{Fwf?w3WapWe|b-CQkqlo z46GmTdPtkGYdI$e(d9Zl=?TU&uv94VR`g|=7xB2Ur%=6id&R2 z4e@fP7`y58O2sl;YBCQFu7>0(lVt-r$9|06Q5V>4=>ycnT}Fyz#9p;3?86`ZD23@7 z7n&`!LXzjxyg*P4Tz`>WVvpU9-<5MDSDcb1 zZaUyN@7mKLEPGS$^odZcW=GLe?3E$JsMR0kcL4#Z=b4P94Q#7O%_60{h>0D(6P*VH z3}>$stt2s!)w4C4 z{zsj!EyQm$2ARSHiRm49r7u)59ZyE}ZznFE7AdF&O&!-&(y=?-7$LWcn4L_Yj%w`qzwz`cLqPRem1zN; z)r)07;JFTnPODe09Z)SF5@^uRuGP~Mjil??oWmJTaCb;yx4?T?d**;AW!pOC^@GnT zaY`WF609J>fG+h?5&#}OD1<%&;_lzM2vw70FNwn2U`-jMH7bJxdQM#6+dPNiiRFGT z7zc{F6bo_V%NILyM?rBnNsH2>Bx~zj)pJ}*FJxW^DC2NLlOI~18Mk`7sl=t`)To6Ui zu4GK6KJx^6Ms4PP?jTn~jW6TOFLl3e2-q&ftT=31P1~a1%7=1XB z+H~<1dh6%L)PbBmtsAr38>m~)?k3}<->1Bs+;227M@?!S+%X&M49o_e)X8|vZiLVa z;zWb1gYokP;Sbao^qD+2ZD_kUn=m=d{Q9_kpGxcbdQ0d5<_OZJ!bZJcmgBRf z!Cdh`qQ_1NLhCulgn{V`C%|wLE8E6vq1Ogm`wb;7Dj+xpwik~?kEzDT$LS?#%!@_{ zhOoXOC95lVcQU^pK5x$Da$TscVXo19Pps zA!(Mk>N|tskqBn=a#aDC4K%jV#+qI$$dPOK6;fPO)0$0j$`OV+mWhE+TqJoF5dgA=TH-}5DH_)H_ zh?b(tUu@65G-O)1ah%|CsU8>cLEy0!Y~#ut#Q|UT92MZok0b4V1INUL-)Dvvq`RZ4 zTU)YVX^r%_lXpn_cwv`H=y49?!m{krF3Rh7O z^z7l4D<+^7E?ji(L5CptsPGttD+Z7{N6c-`0V^lfFjsdO{aJMFfLG9+wClt<=Rj&G zf6NgsPSKMrK6@Kvgarmx{&S48uc+ZLIvk0fbH}q-HQ4FSR33$+%FvNEusl6xin!?e z@rrWUP5U?MbBDeYSO~L;S$hjxISwLr&0BOSd?fOyeCWm6hD~)|_9#jo+PVbAY3wzf zcZS*2pX+8EHD~LdAl>sA*P>`g>>+&B{l94LNLp#KmC)t6`EPhL95s&MMph46Sk^9x%B$RK!2MI--j8nvN31MNLAJBsG`+WMvo1}xpaoq z%+W95_I`J1Pr&Xj`=)eN9!Yt?LWKs3-`7nf)`G6#6#f+=JK!v943*F&veRQxKy-dm(VcnmA?K_l~ zfDWPYl6hhN?17d~^6Zuo@>Hswhq@HrQ)sb7KK^TRhaM2f&td)$6zOn7we@ zd)x4-`?!qzTGDNS-E(^mjM%d46n>vPeMa;%7IJDT(nC)T+WM5F-M$|p(78W!^ck6)A_!6|1o!D97tw8k|5@0(!8W&q9*ovYl)afk z2mxnniCOSh7yHcSoEu8k`i15#oOi^O>uO_oMpT=KQx4Ou{&C4vqZG}YD0q!{RX=`#5wmcHT=hqW3;Yvg5Y^^ ziVunz9V)>2&b^rI{ssTPx26OxTuCw|+{tt_M0TqD?Bg7cWN4 z%UH{38(EW1L^!b~rtWl)#i}=8IUa_oU8**_UEIw+SYMekH;Epx*SA7Hf!EN&t!)zuUca@_Q^zW(u_iK_ zrSw{nva4E6-Npy9?lHAa;b(O z`I74A{jNEXj(#r|eS^Vfj-I!aHv{fEkzv4=F%z0m;3^PXa27k0Hq#RN@J7TwQT4u7 ztisbp3w6#k!RC~!5g-RyjpTth$lf!5HIY_5pfZ8k#q!=q*n>~@93dD|V>=GvH^`zn zVNwT@LfA8^4rpWz%FqcmzX2qEAhQ|_#u}md1$6G9qD%FXLw;fWWvqudd_m+PzI~g3 z`#WPz`M1XUKfT3&T4~XkUie-C#E`GN#P~S(Zx9%CY?EC?KP5KNK`aLlI1;pJvq@d z&0wI|dx##t6Gut6%Y9c-L|+kMov(7Oay++QemvI`JOle{8iE|2kZb=4x%a32?>-B~ z-%W$0t&=mr+WJ3o8d(|^209BapD`@6IMLbcBlWZlrr*Yrn^uRC1(}BGNr!ct z>xzEMV(&;ExHj5cce`pk%6!Xu=)QWtx2gfrAkJY@AZlHWiEe%^_}mdzvs(6>k7$e; ze4i;rv$_Z$K>1Yo9f4&Jbx80?@X!+S{&QwA3j#sAA4U4#v zwZqJ8%l~t7V+~BT%j4Bwga#Aq0&#rBl6p$QFqS{DalLd~MNR8Fru+cdoQ78Dl^K}@l#pmH1-e3?_0tZKdj@d2qu z_{-B11*iuywLJgGUUxI|aen-((KcAZZdu8685Zi1b(#@_pmyAwTr?}#O7zNB7U6P3 zD=_g*ZqJkg_9_X3lStTA-ENl1r>Q?p$X{6wU6~e7OKNIX_l9T# z>XS?PlNEM>P&ycY3sbivwJYAqbQH^)z@PobVRER*Ud*bUi-hjADId`5WqlZ&o+^x= z-Lf_80rC9>tqFBF%x#`o>69>D5f5Kp->>YPi5ArvgDwV#I6!UoP_F0YtfKoF2YduA zCU!1`EB5;r68;WyeL-;(1K2!9sP)at9C?$hhy(dfKKBf}>skPqvcRl>UTAB05SRW! z;`}sPVFFZ4I%YrPEtEsF(|F8gnfGkXI-2DLsj4_>%$_ZX8zVPrO=_$7412)Mr9BH{ zwKD;e13jP2XK&EpbhD-|`T~aI`N(*}*@yeDUr^;-J_`fl*NTSNbupyHLxMxjwmbuw zt3@H|(hvcRldE+OHGL1Y;jtBN76Ioxm@UF1K}DPbgzf_a{`ohXp_u4=ps@x-6-ZT>F z)dU`Jpu~Xn&Qkq2kg%VsM?mKC)ArP5c%r8m4aLqimgTK$atIxt^b8lDVPEGDOJu!) z%rvASo5|v`u_}vleP#wyu1$L5Ta%9YOyS5;w2I!UG&nG0t2YL|DWxr#T7P#Ww8MXDg;-gr`x1?|V`wy&0vm z=hqozzA!zqjOm~*DSI9jk8(9nc4^PL6VOS$?&^!o^Td8z0|eU$9x8s{8H!9zK|)NO zqvK*dKfzG^Dy^vkZU|p9c+uVV3>esY)8SU1v4o{dZ+dPP$OT@XCB&@GJ<5U&$Pw#iQ9qzuc`I_%uT@%-v zLf|?9w=mc;b0G%%{o==Z7AIn{nHk`>(!e(QG%(DN75xfc#H&S)DzSFB6`J(cH!@mX3mv_!BJv?ByIN%r-i{Y zBJU)}Vhu)6oGoQjT2tw&tt4n=9=S*nQV`D_MSw7V8u1-$TE>F-R6Vo0giKnEc4NYZ zAk2$+Tba~}N0wG{$_7eaoCeb*Ubc0 zq~id50^$U>WZjmcnIgsDione)f+T)0ID$xtgM zpGZXmVez0DN!)ioW1E45{!`G9^Y1P1oXhP^rc@c?o+c$^Kj_bn(Uo1H2$|g7=92v- z%Syv9Vo3VcibvH)b78USOTwIh{3%;3skO_htlfS?Cluwe`p&TMwo_WK6Z3Tz#nOoy z_E17(!pJ>`C2KECOo38F1uP0hqBr>%E=LCCCG{j6$b?;r?Fd$4@V-qjEzgWvzbQN%_nlBg?Ly`x-BzO2Nnd1 zuO|li(oo^Rubh?@$q8RVYn*aLnlWO_dhx8y(qzXN6~j>}-^Cuq4>=d|I>vhcjzhSO zU`lu_UZ?JaNs1nH$I1Ww+NJI32^qUikAUfz&k!gM&E_L=e_9}!<(?BfH~aCmI&hfzHi1~ zraRkci>zMPLkad=A&NEnVtQQ#YO8Xh&K*;6pMm$ap_38m;XQej5zEqUr`HdP&cf0i z5DX_c86@15jlm*F}u-+a*^v%u_hpzwN2eT66Zj_1w)UdPz*jI|fJb#kSD_8Q-7q9gf}zNu2h=q{)O*XH8FU)l|m;I;rV^QpXRvMJ|7% zWKTBX*cn`VY6k>mS#cq!uNw7H=GW3?wM$8@odjh$ynPiV7=Ownp}-|fhULZ)5{Z!Q z20oT!6BZTK;-zh=i~RQ$Jw>BTA=T(J)WdnTObDM#61lUm>IFRy@QJ3RBZr)A9CN!T z4k7%)I4yZ-0_n5d083t!=YcpSJ}M5E8`{uIs3L0lIaQws1l2}+w2(}hW&evDlMnC!WV?9U^YXF}!N*iyBGyCyJ<(2(Ca<>!$rID`( zR?V~-53&$6%DhW=)Hbd-oetTXJ-&XykowOx61}1f`V?LF=n8Nb-RLFGqheS7zNM_0 z1ozNap9J4GIM1CHj-%chrCdqPlP307wfrr^=XciOqn?YPL1|ozZ#LNj8QoCtAzY^q z7&b^^K&?fNSWD@*`&I+`l9 zP2SlD0IO?MK60nbucIQWgz85l#+*<{*SKk1K~|x{ux+hn=SvE_XE`oFlr7$oHt-&7 zP{+x)*y}Hnt?WKs_Ymf(J^aoe2(wsMMRPu>Pg8H#x|zQ_=(G5&ieVhvjEXHg1zY?U zW-hcH!DJPr+6Xnt)MslitmnHN(Kgs4)Y`PFcV0Qvemj;GG`kf<>?p})@kd9DA7dqs zNtGRKVr0%x#Yo*lXN+vT;TC{MR}}4JvUHJHDLd-g88unUj1(#7CM<%r!Z1Ve>DD)FneZ| z8Q0yI@i4asJaJ^ge%JPl>zC3+UZ;UDUr7JvUYNMf=M2t{It56OW1nw#K8%sXdX$Yg zpw3T=n}Om?j3-7lu)^XfBQkoaZ(qF0D=Aw&D%-bsox~`8Y|!whzpd5JZ{dmM^A5)M zOwWEM>bj}~885z9bo{kWFA0H(hv(vL$G2;pF$@_M%DSH#g%V*R(>;7Z7eKX&AQv1~ z+lKq=488TbTwA!VtgSHwduwAkGycunrg}>6oiX~;Kv@cZlz=E}POn%BWt{EEd;*GV zmc%PiT~k<(TA`J$#6HVg2HzF6Iw5w9{C63y`Y7?OB$WsC$~6WMm3`UHaWRZLN3nKiV# zE;iiu_)wTr7ZiELH$M^!i5eC9aRU#-RYZhCl1z_aNs@f`tD4A^$xd7I_ijCgI!$+| zsulIT$KB&PZ}T-G;Ibh@UPafvOc-=p7{H-~P)s{3M+;PmXe7}}&Mn+9WT#(Jmt5DW%73OBA$tC#Ug!j1BR~=Xbnaz4hGq zUOjC*z3mKNbrJm1Q!Ft^5{Nd54Q-O7<;n})TTQeLDY3C}RBGwhy*&wgnl8dB4lwkG zBX6Xn#hn|!v7fp@@tj9mUPrdD!9B;tJh8-$aE^t26n_<4^=u~s_MfbD?lHnSd^FGGL6the7a|AbltRGhfET*X;P7=AL?WPjBtt;3IXgUHLFMRBz(aWW_ zZ?%%SEPFu&+O?{JgTNB6^5nR@)rL6DFqK$KS$bvE#&hrPs>sYsW=?XzOyD6ixglJ8rdt{P8 zPAa*+qKt(%ju&jDkbB6x7aE(={xIb*&l=GF(yEnWPj)><_8U5m#gQIIa@l49W_=Qn^RCsYqlEy6Om%!&e~6mCAfDgeXe3aYpHQAA!N|kmIW~Rk}+p6B2U5@|1@7iVbm5&e7E3;c9q@XQlb^JS(gmJl%j9!N|eNQ$*OZf`3!;raRLJ z;X-h>nvB=S?mG!-VH{65kwX-UwNRMQB9S3ZRf`hL z#WR)+rn4C(AG(T*FU}`&UJOU4#wT&oDyZfHP^s9#>V@ens??pxuu-6RCk=Er`DF)X z>yH=P9RtrtY;2|Zg3Tnx3Vb!(lRLedVRmK##_#;Kjnlwq)eTbsY8|D{@Pjn_=kGYO zJq0T<_b;aB37{U`5g6OSG=>|pkj&PohM%*O#>kCPGK2{0*=m(-gKBEOh`fFa6*~Z! zVxw@7BS%e?cV^8{a`Ys4;w=tH4&0izFxgqjE#}UfsE^?w)cYEQjlU|uuv6{>nFTp| zNLjRRT1{g{?U2b6C^w{!s+LQ(n}FfQPDfYPsNV?KH_1HgscqG7z&n3Bh|xNYW4i5i zT4Uv-&mXciu3ej=+4X9h2uBW9o(SF*N~%4%=g|48R-~N32QNq!*{M4~Y!cS4+N=Zr z?32_`YpAeg5&r_hdhJkI4|i(-&BxCKru`zm9`v+CN8p3r9P_RHfr{U$H~RddyZKw{ zR?g5i>ad^Ge&h?LHlP7l%4uvOv_n&WGc$vhn}2d!xIWrPV|%x#2Q-cCbQqQ|-yoTe z_C(P))5e*WtmpB`Fa~#b*yl#vL4D_h;CidEbI9tsE%+{-4ZLKh#9^{mvY24#u}S6oiUr8b0xLYaga!(Fe7Dxi}v6 z%5xNDa~i%tN`Cy_6jbk@aMaY(xO2#vWZh9U?mrNrLs5-*n>04(-Dlp%6AXsy;f|a+ z^g~X2LhLA>xy(8aNL9U2wr=ec%;J2hEyOkL*D%t4cNg7WZF@m?kF5YGvCy`L5jus# zGP8@iGTY|ov#t&F$%gkWDoMR7v*UezIWMeg$C2~WE9*5%}$3!eFiFJ?hypfIA(PQT@=B|^Ipcu z{9cM3?rPF|gM~{G)j*af1hm+l92W7HRpQ*hSMDbh(auwr}VBG7`ldp>`FZ^amvau zTa~Y7%tH@>|BB6kSRGiWZFK?MIzxEHKGz#P!>rB-90Q_UsZ=uW6aTzxY{MPP@1rw- z&RP^Ld%HTo($y?6*aNMz8h&E?_PiO{jq%u4kr#*uN&Q+Yg1Rn831U4A6u#XOzaSL4 zrcM+0v@%On8N*Mj!)&IzXW6A80bUK&3w|z06cP!UD^?_rb_(L-u$m+#%YilEjkrlxthGCLQ@Q?J!p?ggv~0 z!qipxy&`w48T0(Elsz<^hp_^#1O1cNJ1UG=61Nc=)rlRo_P6v&&h??Qvv$ifC3oJh zo)ZZhU5enAqU%YB>+FU!1vW)i$m-Z%w!c&92M1?))n4z1a#4-FufZ$DatpJ^q)_Zif z;Br{HmZ|8LYRTi`#?TUfd;#>c4@2qM5_(H+Clt@kkQT+kx78KACyvY)?^zhyuN_Z& z-*9_o_f3IC2lX^(aLeqv#>qnelb6_jk+lgQh;TN>+6AU9*6O2h_*=74m;xSPD1^C9 zE0#!+B;utJ@8P6_DKTQ9kNOf`C*Jj0QAzsngKMQVDUsp=k~hd@wt}f{@$O*xI!a?p z6Gti>uE}IKAaQwKHRb0DjmhaF#+{9*=*^0)M-~6lPS-kCI#RFGJ-GyaQ+rhbmhQef zwco))WNA1LFr|J3Qsp4ra=_j?Y%b{JWMX6Zr`$;*V`l`g7P0sP?Y1yOY;e0Sb!AOW0Em=U8&i8EKxTd$dX6=^Iq5ZC%zMT5Jjj%0_ zbf|}I=pWjBKAx7wY<4-4o&E6vVStcNlT?I18f5TYP9!s|5yQ_C!MNnRyDt7~u~^VS@kKd}Zwc~? z=_;2}`Zl^xl3f?ce8$}g^V)`b8Pz88=9FwYuK_x%R?sbAF-dw`*@wokEC3mp0Id>P z>OpMGxtx!um8@gW2#5|)RHpRez+)}_p;`+|*m&3&qy{b@X>uphcgAVgWy`?Nc|NlH z75_k2%3h7Fy~EkO{vBMuzV7lj4B}*1Cj(Ew7oltspA6`d69P`q#Y+rHr5-m5&be&( zS1GcP5u#aM9V{fUQTfHSYU`kW&Wsxeg;S*{H_CdZ$?N>S$JPv!_6T(NqYPaS{yp0H7F~7vy#>UHJr^lV?=^vt4?8$v8vkI-1eJ4{iZ!7D5A zg_!ZxZV+9Wx5EIZ1%rbg8`-m|=>knmTE1cpaBVew_iZpC1>d>qd3`b6<(-)mtJBmd zjuq-qIxyKvIs!w4$qpl{0cp^-oq<=-IDEYV7{pvfBM7tU+ zfX3fc+VGtqjPIIx`^I0i>*L-NfY=gFS+|sC75Cg;2<)!Y`&p&-AxfOHVADHSv1?7t zlOKyXxi|7HdwG5s4T0))dWudvz8SZpxd<{z&rT<34l}XaaP86x)Q=2u5}1@Sgc41D z2gF)|aD7}UVy)bnm788oYp}Es!?|j73=tU<_+A4s5&it~_K4 z;^$i0Vnz8y&I!abOkzN|Vz;kUTya#Wi07>}Xf^7joZMiHH3Mdy@e_7t?l8^A!r#jTBau^wn#{|!tTg=w01EQUKJOca!I zV*>St2399#)bMF++1qS8T2iO3^oA`i^Px*i)T_=j=H^Kp4$Zao(>Y)kpZ=l#dSgcUqY=7QbGz9mP9lHnII8vl?yY9rU+i%X)-j0&-- zrtaJsbkQ$;DXyIqDqqq)LIJQ!`MIsI;goVbW}73clAjN;1Rtp7%{67uAfFNe_hyk= zn=8Q1x*zHR?txU)x9$nQu~nq7{Gbh7?tbgJ>i8%QX3Y8%T{^58W^{}(!9oPOM+zF3 zW`%<~q@W}9hoes56uZnNdLkgtcRqPQ%W8>o7mS(j5Sq_nN=b0A`Hr%13P{uvH?25L zMfC&Z0!{JBGiKoVwcIhbbx{I35o}twdI_ckbs%1%AQ(Tdb~Xw+sXAYcOoH_9WS(yM z2dIzNLy4D%le8Fxa31fd;5SuW?ERAsagZVEo^i};yjBhbxy9&*XChFtOPV8G77{8! zlYemh2vp7aBDMGT;YO#=YltE~(Qv~e7c=6$VKOxHwvrehtq>n|w}vY*YvXB%a58}n zqEBR4zueP@A~uQ2x~W-{o3|-xS@o>Ad@W99)ya--dRx;TZLL?5E(xstg(6SwDIpL5 zMZ)+)+&(hYL(--dxIKB*#v4mDq=0ve zNU~~jk426bXlS8%lcqsvuqbpgn zbFgxap;17;@xVh+Y~9@+-lX@LQv^Mw=yCM&2!%VCfZsiwN>DI=O?vHupbv9!4d*>K zcj@a5vqjcjpwkm@!2dxzzJGQ7#ujW(IndUuYC)i3N2<*doRGX8a$bSbyRO#0rA zUpFyEGx4S9$TKuP9BybRtjcAn$bGH-9>e(V{pKYPM3waYrihBCQf+UmIC#E=9v?or z_7*yzZfT|)8R6>s(lv6uzosT%WoR`bQIv(?llcH2Bd@26?zU%r1K25qscRrE1 z9TIIP_?`78@uJ{%I|_K;*syVinV;pCW!+zY-!^#n{3It^6EKw{~WIA0pf_hVzEZy zFzE=d-NC#mge{4Fn}we02-%Zh$JHKpXX3qF<#8__*I}+)Npxm?26dgldWyCmtwr9c zOXI|P0zCzn8M_Auv*h9;2lG}x*E|u2!*-s}moqS%Z`?O$<0amJG9n`dOV4**mypG- zE}In1pOQ|;@@Jm;I#m}jkQegIXag4K%J;C7<@R2X8IdsCNqrbsaUZZRT|#6=N!~H} zlc2hPngy9r+Gm_%tr9V&HetvI#QwUBKV&6NC~PK>HNQ3@fHz;J&rR7XB>sWkXKp%A ziLlogA`I*$Z7KzLaX^H_j)6R|9Q>IHc? z{s0MsOW>%xW|JW=RUxY@@0!toq`QXa=`j;)o2iDBiDZ7c4Bc>BiDTw+zk}Jm&vvH8qX$R`M6Owo>m%n`eizBf!&9X6 z)f{GpMak@NWF+HNg*t#H5yift5@QhoYgT7)jxvl&O=U54Z>FxT5prvlDER}AwrK4Q z*&JP9^k332OxC$(E6^H`#zw|K#cpwy0i*+!z{T23;dqUKbjP!-r*@_!sp+Uec@^f0 zIJMjqhp?A#YoX5EB%iWu;mxJ1&W6Nb4QQ@GElqNjFNRc*=@aGc$PHdoUptckkoOZC zk@c9i+WVnDI=GZ1?lKjobDl%nY2vW~d)eS6Lch&J zDi~}*fzj9#<%xg<5z-4(c}V4*pj~1z2z60gZc}sAmys^yvobWz)DKDGWuVpp^4-(!2Nn7 z3pO})bO)({KboXlQA>3PIlg@Ie$a=G;MzVeft@OMcKEjIr=?;=G0AH?dE_DcNo%n$_bFjqQ8GjeIyJP^NkX~7e&@+PqnU-c3@ABap z=}IZvC0N{@fMDOpatOp*LZ7J6Hz@XnJzD!Yh|S8p2O($2>A4hbpW{8?#WM`uJG>?} zwkDF3dimqejl$3uYoE7&pr5^f4QP-5TvJ;5^M?ZeJM8ywZ#Dm`kR)tpYieQU;t2S! z05~aeOBqKMb+`vZ2zfR*2(&z`Y1VROAcR(^Q7ZyYlFCLHSrTOQm;pnhf3Y@WW#gC1 z7b$_W*ia0@2grK??$pMHK>a$;J)xIx&fALD4)w=xlT=EzrwD!)1g$2q zy8GQ+r8N@?^_tuCKVi*q_G*!#NxxY#hpaV~hF} zF1xXy#XS|q#)`SMAA|46+UnJZ__lETDwy}uecTSfz69@YO)u&QORO~F^>^^j-6q?V z-WK*o?XSw~ukjoIT9p6$6*OStr`=+;HrF#)p>*>e|gy0D9G z#TN(VSC11^F}H#?^|^ona|%;xCC!~H3~+a>vjyRC5MPGxFqkj6 zttv9I_fv+5$vWl2r8+pXP&^yudvLxP44;9XzUr&a$&`?VNhU^$J z`3m68BAuA?ia*IF%Hs)@>xre4W0YoB^(X8RwlZ?pKR)rvGX?u&K`kb8XBs^pe}2v* z_NS*z7;4%Be$ts_emapc#zKjVMEqn8;aCX=dISG3zvJP>l4zHdpUwARLixQSFzLZ0 z$$Q+9fAnVjA?7PqANPiH*XH~VhrVfW11#NkAKjfjQN-UNz?ZT}SG#*sk*)VUXZ1$P zdxiM@I2RI7Tr043ZgWd3G^k56$Non@LKE|zLwBgXW#e~{7C{iB3&UjhKZPEj#)cH9 z%HUDubc0u@}dBz>4zU;sTluxBtCl!O4>g9ywc zhEiM-!|!C&LMjMNs6dr6Q!h{nvTrNN0hJ+w*h+EfxW=ro zxAB%*!~&)uaqXyuh~O`J(6e!YsD0o0l_ung1rCAZt~%4R{#izD2jT~${>f}m{O!i4 z`#UGbiSh{L=FR`Q`e~9wrKHSj?I>eXHduB`;%TcCTYNG<)l@A%*Ld?PK=fJi}J? z9T-|Ib8*rLE)v_3|1+Hqa!0ch>f% zfNFz@o6r5S`QQJCwRa4zgx$7AyQ7ZTv2EM7ZQHh!72CFL+qT`Y)k!)|Zr;7mcfV8T z)PB$1r*5rUzgE@y^E_kDG3Ol5n6q}eU2hJcXY7PI1}N=>nwC6k%nqxBIAx4Eix*`W zch0}3aPFe5*lg1P(=7J^0ZXvpOi9v2l*b?j>dI%iamGp$SmFaxpZod*TgYiyhF0= za44lXRu%9MA~QWN;YX@8LM32BqKs&W4&a3ve9C~ndQq>S{zjRNj9&&8k-?>si8)^m zW%~)EU)*$2YJzTXjRV=-dPAu;;n2EDYb=6XFyz`D0f2#29(mUX}*5~KU3k>$LwN#OvBx@ zl6lC>UnN#0?mK9*+*DMiboas!mmGnoG%gSYeThXI<=rE(!Pf-}oW}?yDY0804dH3o zo;RMFJzxP|srP-6ZmZ_peiVycfvH<`WJa9R`Z#suW3KrI*>cECF(_CB({ToWXSS18#3%vihZZJ{BwJPa?m^(6xyd1(oidUkrOU zlqyRQUbb@W_C)5Q)%5bT3K0l)w(2cJ-%?R>wK35XNl&}JR&Pn*laf1M#|s4yVXQS# zJvkT$HR;^3k{6C{E+{`)J+~=mPA%lv1T|r#kN8kZP}os;n39exCXz^cc{AN(Ksc%} zA561&OeQU8gIQ5U&Y;Ca1TatzG`K6*`9LV<|GL-^=qg+nOx~6 zBEMIM7Q^rkuhMtw(CZtpU(%JlBeV?KC+kjVDL34GG1sac&6(XN>nd+@Loqjo%i6I~ zjNKFm^n}K=`z8EugP20fd_%~$Nfu(J(sLL1gvXhxZt|uvibd6rLXvM%!s2{g0oNA8 z#Q~RfoW8T?HE{ge3W>L9bx1s2_L83Odx)u1XUo<`?a~V-_ZlCeB=N-RWHfs1(Yj!_ zP@oxCRysp9H8Yy@6qIc69TQx(1P`{iCh)8_kH)_vw1=*5JXLD(njxE?2vkOJ z>qQz!*r`>X!I69i#1ogdVVB=TB40sVHX;gak=fu27xf*}n^d>@*f~qbtVMEW!_|+2 zXS`-E%v`_>(m2sQnc6+OA3R z-6K{6$KZsM+lF&sn~w4u_md6J#+FzqmtncY;_ z-Q^D=%LVM{A0@VCf zV9;?kF?vV}*=N@FgqC>n-QhKJD+IT7J!6llTEH2nmUxKiBa*DO4&PD5=HwuD$aa(1 z+uGf}UT40OZAH@$jjWoI7FjOQAGX6roHvf_wiFKBfe4w|YV{V;le}#aT3_Bh^$`Pp zJZGM_()iFy#@8I^t{ryOKQLt%kF7xq&ZeD$$ghlTh@bLMv~||?Z$#B2_A4M&8)PT{ zyq$BzJpRrj+=?F}zH+8XcPvhRP+a(nnX2^#LbZqgWQ7uydmIM&FlXNx4o6m;Q5}rB z^ryM&o|~a-Zb20>UCfSFwdK4zfk$*~<|90v0=^!I?JnHBE{N}74iN;w6XS=#79G+P zB|iewe$kk;9^4LinO>)~KIT%%4Io6iFFXV9gJcIvu-(!um{WfKAwZDmTrv=wb#|71 zWqRjN8{3cRq4Ha2r5{tw^S>0DhaC3m!i}tk9q08o>6PtUx1GsUd{Z17FH45rIoS+oym1>3S0B`>;uo``+ADrd_Um+8s$8V6tKsA8KhAm z{pTv@zj~@+{~g&ewEBD3um9@q!23V_8Nb0_R#1jcg0|MyU)?7ua~tEY63XSvqwD`D zJ+qY0Wia^BxCtXpB)X6htj~*7)%un+HYgSsSJPAFED7*WdtlFhuJj5d3!h8gt6$(s ztrx=0hFH8z(Fi9}=kvPI?07j&KTkssT=Vk!d{-M50r!TsMD8fPqhN&%(m5LGpO>}L zse;sGl_>63FJ)(8&8(7Wo2&|~G!Lr^cc!uuUBxGZE)ac7Jtww7euxPo)MvxLXQXlk zeE>E*nMqAPwW0&r3*!o`S7wK&078Q#1bh!hNbAw0MFnK-2gU25&8R@@j5}^5-kHeR z!%krca(JG%&qL2mjFv380Gvb*eTLllTaIpVr3$gLH2e3^xo z=qXjG0VmES%OXAIsOQG|>{aj3fv+ZWdoo+a9tu8)4AyntBP>+}5VEmv@WtpTo<-aH zF4C(M#dL)MyZmU3sl*=TpAqU#r>c8f?-zWMq`wjEcp^jG2H`8m$p-%TW?n#E5#Th+ z7Zy#D>PPOA4|G@-I$!#Yees_9Ku{i_Y%GQyM)_*u^nl+bXMH!f_ z8>BM|OTex;vYWu`AhgfXFn)0~--Z7E0WR-v|n$XB-NOvjM156WR(eu z(qKJvJ%0n+%+%YQP=2Iz-hkgI_R>7+=)#FWjM#M~Y1xM8m_t8%=FxV~Np$BJ{^rg9 z5(BOvYfIY{$h1+IJyz-h`@jhU1g^Mo4K`vQvR<3wrynWD>p{*S!kre-(MT&`7-WK! zS}2ceK+{KF1yY*x7FH&E-1^8b$zrD~Ny9|9(!1Y)a#)*zf^Uo@gy~#%+*u`U!R`^v zCJ#N!^*u_gFq7;-XIYKXvac$_=booOzPgrMBkonnn%@#{srUC<((e*&7@YR?`CP;o zD2*OE0c%EsrI72QiN`3FpJ#^Bgf2~qOa#PHVmbzonW=dcrs92>6#{pEnw19AWk%;H zJ4uqiD-dx*w2pHf8&Jy{NXvGF^Gg!ungr2StHpMQK5^+ zEmDjjBonrrT?d9X;BHSJeU@lX19|?On)(Lz2y-_;_!|}QQMsq4Ww9SmzGkzVPQTr* z)YN>_8i^rTM>Bz@%!!v)UsF&Nb{Abz>`1msFHcf{)Ufc_a-mYUPo@ei#*%I_jWm#7 zX01=Jo<@6tl`c;P_uri^gJxDVHOpCano2Xc5jJE8(;r@y6THDE>x*#-hSKuMQ_@nc z68-JLZyag_BTRE(B)Pw{B;L0+Zx!5jf%z-Zqug*og@^ zs{y3{Za(0ywO6zYvES>SW*cd4gwCN^o9KQYF)Lm^hzr$w&spGNah6g>EQBufQCN!y zI5WH$K#67$+ic{yKAsX@el=SbBcjRId*cs~xk~3BBpQsf%IsoPG)LGs zdK0_rwz7?L0XGC^2$dktLQ9qjwMsc1rpGx2Yt?zmYvUGnURx(1k!kmfPUC@2Pv;r9 z`-Heo+_sn+!QUJTAt;uS_z5SL-GWQc#pe0uA+^MCWH=d~s*h$XtlN)uCI4$KDm4L$ zIBA|m0o6@?%4HtAHRcDwmzd^(5|KwZ89#UKor)8zNI^EsrIk z1QLDBnNU1!PpE3iQg9^HI){x7QXQV{&D>2U%b_II>*2*HF2%>KZ>bxM)Jx4}|CCEa`186nD_B9h`mv6l45vRp*L+z_nx5i#9KvHi>rqxJIjKOeG(5lCeo zLC|-b(JL3YP1Ds=t;U!Y&Gln*Uwc0TnDSZCnh3m$N=xWMcs~&Rb?w}l51ubtz=QUZsWQhWOX;*AYb)o(^<$zU_v=cFwN~ZVrlSLx| zpr)Q7!_v*%U}!@PAnZLqOZ&EbviFbej-GwbeyaTq)HSBB+tLH=-nv1{MJ-rGW%uQ1 znDgP2bU@}!Gd=-;3`KlJYqB@U#Iq8Ynl%eE!9g;d*2|PbC{A}>mgAc8LK<69qcm)piu?`y~3K8zlZ1>~K_4T{%4zJG6H?6%{q3B-}iP_SGXELeSv*bvBq~^&C=3TsP z9{cff4KD2ZYzkArq=;H(Xd)1CAd%byUXZdBHcI*%a24Zj{Hm@XA}wj$=7~$Q*>&4} z2-V62ek{rKhPvvB711`qtAy+q{f1yWuFDcYt}hP)Vd>G?;VTb^P4 z(QDa?zvetCoB_)iGdmQ4VbG@QQ5Zt9a&t(D5Rf#|hC`LrONeUkbV)QF`ySE5x+t_v z-(cW{S13ye9>gtJm6w&>WwJynxJQm8U2My?#>+(|)JK}bEufIYSI5Y}T;vs?rzmLE zAIk%;^qbd@9WUMi*cGCr=oe1-nthYRQlhVHqf{ylD^0S09pI}qOQO=3&dBsD)BWo# z$NE2Ix&L&4|Aj{;ed*A?4z4S!7o_Kg^8@%#ZW26_F<>y4ghZ0b|3+unIoWDUVfen~ z`4`-cD7qxQSm9hF-;6WvCbu$t5r$LCOh}=`k1(W<&bG-xK{VXFl-cD%^Q*x-9eq;k8FzxAqZB zH@ja_3%O7XF~>owf3LSC_Yn!iO}|1Uc5uN{Wr-2lS=7&JlsYSp3IA%=E?H6JNf()z zh>jA>JVsH}VC>3Be>^UXk&3o&rK?eYHgLwE-qCHNJyzDLmg4G(uOFX5g1f(C{>W3u zn~j`zexZ=sawG8W+|SErqc?uEvQP(YT(YF;u%%6r00FP;yQeH)M9l+1Sv^yddvGo- z%>u>5SYyJ|#8_j&%h3#auTJ!4y@yEg<(wp#(~NH zXP7B#sv@cW{D4Iz1&H@5wW(F82?-JmcBt@Gw1}WK+>FRXnX(8vwSeUw{3i%HX6-pvQS-~Omm#x-udgp{=9#!>kDiLwqs_7fYy{H z)jx_^CY?5l9#fR$wukoI>4aETnU>n<$UY!JDlIvEti908)Cl2Ziyjjtv|P&&_8di> z<^amHu|WgwMBKHNZ)t)AHII#SqDIGTAd<(I0Q_LNPk*?UmK>C5=rIN^gs}@65VR*!J{W;wp5|&aF8605*l-Sj zQk+C#V<#;=Sl-)hzre6n0n{}|F=(#JF)X4I4MPhtm~qKeR8qM?a@h!-kKDyUaDrqO z1xstrCRCmDvdIFOQ7I4qesby8`-5Y>t_E1tUTVOPuNA1De9| z8{B0NBp*X2-ons_BNzb*Jk{cAJ(^F}skK~i;p0V(R7PKEV3bB;syZ4(hOw47M*-r8 z3qtuleeteUl$FHL$)LN|q8&e;QUN4(id`Br{rtsjpBdriO}WHLcr<;aqGyJP{&d6? zMKuMeLbc=2X0Q_qvSbl3r?F8A^oWw9Z{5@uQ`ySGm@DUZ=XJ^mKZ-ipJtmiXjcu<%z?Nj%-1QY*O{NfHd z=V}Y(UnK=f?xLb-_~H1b2T&0%O*2Z3bBDf06-nO*q%6uEaLs;=omaux7nqqW%tP$i zoF-PC%pxc(ymH{^MR_aV{@fN@0D1g&zv`1$Pyu3cvdR~(r*3Y%DJ@&EU?EserVEJ` zEprux{EfT+(Uq1m4F?S!TrZ+!AssSdX)fyhyPW6C`}ko~@y#7acRviE(4>moNe$HXzf zY@@fJa~o_r5nTeZ7ceiXI=k=ISkdp1gd1p)J;SlRn^5;rog!MlTr<<6-U9|oboRBN zlG~o*dR;%?9+2=g==&ZK;Cy0pyQFe)x!I!8g6;hGl`{{3q1_UzZy)J@c{lBIEJVZ& z!;q{8h*zI!kzY#RO8z3TNlN$}l;qj10=}du!tIKJs8O+?KMJDoZ+y)Iu`x`yJ@krO zwxETN$i!bz8{!>BKqHpPha{96eriM?mST)_9Aw-1X^7&;Bf=c^?17k)5&s08^E$m^ zRt02U_r!99xfiow-XC~Eo|Yt8t>32z=rv$Z;Ps|^26H73JS1Xle?;-nisDq$K5G3y znR|l8@rlvv^wj%tdgw+}@F#Ju{SkrQdqZ?5zh;}|IPIdhy3ivi0Q41C@4934naAaY z%+otS8%Muvrr{S-Y96G?b2j0ldu1&coOqsq^vfcUT3}#+=#;fii6@M+hDp}dr9A0Y zjbhvqmB03%4jhsZ{_KQfGh5HKm-=dFxN;3tnwBej^uzcVLrrs z>eFP-jb#~LE$qTP9JJ;#$nVOw%&;}y>ezA6&i8S^7YK#w&t4!A36Ub|or)MJT z^GGrzgcnQf6D+!rtfuX|Pna`Kq*ScO#H=de2B7%;t+Ij<>N5@(Psw%>nT4cW338WJ z>TNgQ^!285hS1JoHJcBk;3I8%#(jBmcpEkHkQDk%!4ygr;Q2a%0T==W zT#dDH>hxQx2E8+jE~jFY$FligkN&{vUZeIn*#I_Ca!l&;yf){eghi z>&?fXc-C$z8ab$IYS`7g!2#!3F@!)cUquAGR2oiR0~1pO<$3Y$B_@S2dFwu~B0e4D z6(WiE@O{(!vP<(t{p|S5#r$jl6h;3@+ygrPg|bBDjKgil!@Sq)5;rXNjv#2)N5_nn zuqEURL>(itBYrT&3mu-|q;soBd52?jMT75cvXYR!uFuVP`QMot+Yq?CO%D9$Jv24r zhq1Q5`FD$r9%&}9VlYcqNiw2#=3dZsho0cKKkv$%X&gmVuv&S__zyz@0zmZdZI59~s)1xFs~kZS0C^271hR*O z9nt$5=y0gjEI#S-iV0paHx!|MUNUq&$*zi>DGt<#?;y;Gms|dS{2#wF-S`G3$^$7g z1#@7C65g$=4Ij?|Oz?X4=zF=QfixmicIw{0oDL5N7iY}Q-vcVXdyQNMb>o_?3A?e6 z$4`S_=6ZUf&KbMgpn6Zt>6n~)zxI1>{HSge3uKBiN$01WB9OXscO?jd!)`?y5#%yp zJvgJU0h+|^MdA{!g@E=dJuyHPOh}i&alC+cY*I3rjB<~DgE{`p(FdHuXW;p$a+%5` zo{}x#Ex3{Sp-PPi)N8jGVo{K!$^;z%tVWm?b^oG8M?Djk)L)c{_-`@F|8LNu|BTUp zQY6QJVzVg8S{8{Pe&o}Ux=ITQ6d42;0l}OSEA&Oci$p?-BL187L6rJ>Q)aX0)Wf%T zneJF2;<-V%-VlcA?X03zpf;wI&8z9@Hy0BZm&ac-Gdtgo>}VkZYk##OOD+nVOKLFJ z5hgXAhkIzZtCU%2M#xl=D7EQPwh?^gZ_@0p$HLd*tF>qgA_P*dP;l^cWm&iQSPJZE zBoipodanrwD0}}{H#5o&PpQpCh61auqlckZq2_Eg__8;G-CwyH#h1r0iyD#Hd_$WgM89n+ldz;=b!@pvr4;x zs|YH}rQuCyZO!FWMy%lUyDE*0)(HR}QEYxIXFexCkq7SHmSUQ)2tZM2s`G<9dq;Vc ziNVj5hiDyqET?chgEA*YBzfzYh_RX#0MeD@xco%)ON%6B7E3#3iFBkPK^P_=&8$pf zpM<0>QmE~1FX1>mztm>JkRoosOq8cdJ1gF5?%*zMDak%qubN}SM!dW6fgH<*F>4M7 zX}%^g{>ng^2_xRNGi^a(epr8SPSP>@rg7s=0PO-#5*s}VOH~4GpK9<4;g=+zuJY!& ze_ld=ybcca?dUI-qyq2Mwl~-N%iCGL;LrE<#N}DRbGow7@5wMf&d`kT-m-@geUI&U z0NckZmgse~(#gx;tsChgNd|i1Cz$quL>qLzEO}ndg&Pg4f zy`?VSk9X5&Ab_TyKe=oiIiuNTWCsk6s9Ie2UYyg1y|i}B7h0k2X#YY0CZ;B7!dDg7 z_a#pK*I7#9-$#Iev5BpN@xMq@mx@TH@SoNWc5dv%^8!V}nADI&0K#xu_#y)k%P2m~ zqNqQ{(fj6X8JqMe5%;>MIkUDd#n@J9Dm~7_wC^z-Tcqqnsfz54jPJ1*+^;SjJzJhG zIq!F`Io}+fRD>h#wjL;g+w?Wg`%BZ{f()%Zj)sG8permeL0eQ9vzqcRLyZ?IplqMg zpQaxM11^`|6%3hUE9AiM5V)zWpPJ7nt*^FDga?ZP!U1v1aeYrV2Br|l`J^tgLm;~%gX^2l-L9L`B?UDHE9_+jaMxy|dzBY4 zjsR2rcZ6HbuyyXsDV(K0#%uPd#<^V%@9c7{6Qd_kQEZL&;z_Jf+eabr)NF%@Ulz_a1e(qWqJC$tTC! zwF&P-+~VN1Vt9OPf`H2N{6L@UF@=g+xCC_^^DZ`8jURfhR_yFD7#VFmklCR*&qk;A zzyw8IH~jFm+zGWHM5|EyBI>n3?2vq3W?aKt8bC+K1`YjklQx4*>$GezfU%E|>Or9Y zNRJ@s(>L{WBXdNiJiL|^In*1VA`xiE#D)%V+C;KuoQi{1t3~4*8 z;tbUGJ2@2@$XB?1!U;)MxQ}r67D&C49k{ceku^9NyFuSgc}DC2pD|+S=qLH&L}Vd4 zM=-UK4{?L?xzB@v;qCy}Ib65*jCWUh(FVc&rg|+KnopG`%cb>t;RNv=1%4= z#)@CB7i~$$JDM>q@4ll8{Ja5Rsq0 z$^|nRac)f7oZH^=-VdQldC~E_=5%JRZSm!z8TJocv`w<_e0>^teZ1en^x!yQse%Lf z;JA5?0vUIso|MS03y${dX19A&bU4wXS~*T7h+*4cgSIX11EB?XGiBS39hvWWuyP{!5AY^x5j{!c?z<}7f-kz27%b>llPq%Z7hq+CU|Ev2 z*jh(wt-^7oL`DQ~Zw+GMH}V*ndCc~ zr>WVQHJQ8ZqF^A7sH{N5~PbeDihT$;tUP`OwWn=j6@L+!=T|+ze%YQ zO+|c}I)o_F!T(^YLygYOTxz&PYDh9DDiv_|Ewm~i7|&Ck^$jsv_0n_}q-U5|_1>*L44)nt!W|;4q?n&k#;c4wpSx5atrznZbPc;uQI^I}4h5Fy`9J)l z7yYa7Rg~f@0oMHO;seQl|E@~fd|532lLG#e6n#vXrfdh~?NP){lZ z&3-33d;bUTEAG=!4_{YHd3%GCV=WS|2b)vZgX{JC)?rsljjzWw@Hflbwg3kIs^l%y zm3fVP-55Btz;<-p`X(ohmi@3qgdHmwXfu=gExL!S^ve^MsimP zNCBV>2>=BjLTobY^67f;8mXQ1YbM_NA3R^s z{zhY+5@9iYKMS-)S>zSCQuFl!Sd-f@v%;;*fW5hme#xAvh0QPtJ##}b>&tth$)6!$ z0S&b2OV-SE<|4Vh^8rs*jN;v9aC}S2EiPKo(G&<6C|%$JQ{;JEg-L|Yob*<-`z?AsI(~U(P>cC=1V$OETG$7i# zG#^QwW|HZuf3|X|&86lOm+M+BE>UJJSSAAijknNp*eyLUq=Au z7&aqR(x8h|>`&^n%p#TPcC@8@PG% zM&7k6IT*o-NK61P1XGeq0?{8kA`x;#O+|7`GTcbmyWgf^JvWU8Y?^7hpe^85_VuRq7yS~8uZ=Cf%W^OfwF_cbBhr`TMw^MH0<{3y zU=y;22&oVlrH55eGNvoklhfPM`bPX`|C_q#*etS^O@5PeLk(-DrK`l|P*@#T4(kRZ z`AY7^%&{!mqa5}q%<=x1e29}KZ63=O>89Q)yO4G@0USgbGhR#r~OvWI4+yu4*F8o`f?EG~x zBCEND=ImLu2b(FDF3sOk_|LPL!wrzx_G-?&^EUof1C~A{feam{2&eAf@2GWem7! z|LV-lff1Dk+mvTw@=*8~0@_Xu@?5u?-u*r8E7>_l1JRMpi{9sZqYG+#Ty4%Mo$`ds zsVROZH*QoCErDeU7&=&-ma>IUM|i_Egxp4M^|%^I7ecXzq@K8_oz!}cHK#>&+$E4rs2H8Fyc)@Bva?(KO%+oc!+3G0&Rv1cP)e9u_Y|dXr#!J;n%T4+9rTF>^m_4X3 z(g+$G6Zb@RW*J-IO;HtWHvopoVCr7zm4*h{rX!>cglE`j&;l_m(FTa?hUpgv%LNV9 zkSnUu1TXF3=tX)^}kDZk|AF%7FmLv6sh?XCORzhTU%d>y4cC;4W5mn=i6vLf2 ztbTQ8RM@1gn|y$*jZa8&u?yTOlNo{coXPgc%s;_Y!VJw2Z1bf%57p%kC1*5e{bepl zwm?2YGk~x=#69_Ul8A~(BB}>UP27=M)#aKrxWc-)rLL+97=>x|?}j)_5ewvoAY?P| z{ekQQbmjbGC%E$X*x-M=;Fx}oLHbzyu=Dw>&WtypMHnOc92LSDJ~PL7sU!}sZw`MY z&3jd_wS8>a!si2Y=ijCo(rMnAqq z-o2uzz}Fd5wD%MAMD*Y&=Ct?|B6!f0jfiJt;hvkIyO8me(u=fv_;C;O4X^vbO}R_% zo&Hx7C@EcZ!r%oy}|S-8CvPR?Ns0$j`FtMB;h z`#0Qq)+6Fxx;RCVnhwp`%>0H4hk(>Kd!(Y}>U+Tr_6Yp?W%jt_zdusOcA$pTA z(4l9$K=VXT2ITDs!OcShuUlG=R6#x@t74B2x7Dle%LGwsZrtiqtTuZGFUio_Xwpl} z=T7jdfT~ld#U${?)B67E*mP*E)XebDuMO(=3~Y=}Z}rm;*4f~7ka196QIHj;JK%DU z?AQw4I4ZufG}gmfVQ3w{snkpkgU~Xi;}V~S5j~;No^-9eZEYvA`Et=Q4(5@qcK=Pr zk9mo>v!%S>YD^GQc7t4c!C4*qU76b}r(hJhO*m-s9OcsktiXY#O1<OoH z#J^Y@1A;nRrrxNFh?3t@Hx9d>EZK*kMb-oe`2J!gZ;~I*QJ*f1p93>$lU|4qz!_zH z&mOaj#(^uiFf{*Nq?_4&9ZssrZeCgj1J$1VKn`j+bH%9#C5Q5Z@9LYX1mlm^+jkHf z+CgcdXlX5);Ztq6OT@;UK_zG(M5sv%I`d2(i1)>O`VD|d1_l(_aH(h>c7fP_$LA@d z6Wgm))NkU!v^YaRK_IjQy-_+>f_y(LeS@z+B$5be|FzXqqg}`{eYpO;sXLrU{*fJT zQHUEXoWk%wh%Kal`E~jiu@(Q@&d&dW*!~9;T=gA{{~NJwQvULf;s43Ku#A$NgaR^1 z%U3BNX`J^YE-#2dM*Ov*CzGdP9^`iI&`tmD~Bwqy4*N=DHt%RycykhF* zc7BcXG28Jvv(5G8@-?OATk6|l{Rg1 zwdU2Md1Qv?#$EO3E}zk&9>x1sQiD*sO0dGSUPkCN-gjuppdE*%*d*9tEWyQ%hRp*7 zT`N^=$PSaWD>f;h@$d2Ca7 z8bNsm14sdOS%FQhMn9yC83$ z-YATg3X!>lWbLUU7iNk-`O%W8MrgI03%}@6l$9+}1KJ1cTCiT3>^e}-cTP&aEJcUt zCTh_xG@Oa-v#t_UDKKfd#w0tJfA+Ash!0>X&`&;2%qv$!Gogr4*rfMcKfFl%@{ztA zwoAarl`DEU&W_DUcIq-{xaeRu(ktyQ64-uw?1S*A>7pRHH5_F)_yC+2o@+&APivkn zwxDBp%e=?P?3&tiVQb8pODI}tSU8cke~T#JLAxhyrZ(yx)>fUhig`c`%;#7Ot9le# zSaep4L&sRBd-n&>6=$R4#mU8>T>=pB)feU9;*@j2kyFHIvG`>hWYJ_yqv?Kk2XTw` z42;hd=hm4Iu0h{^M>-&c9zKPtqD>+c$~>k&Wvq#>%FjOyifO%RoFgh*XW$%Hz$y2-W!@W6+rFJja=pw-u_s0O3WMVgLb&CrCQ)8I^6g!iQj%a%#h z<~<0S#^NV4n!@tiKb!OZbkiSPp~31?f9Aj#fosfd*v}j6&7YpRGgQ5hI_eA2m+Je) zT2QkD;A@crBzA>7T zw4o1MZ_d$)puHvFA2J|`IwSXKZyI_iK_}FvkLDaFj^&6}e|5@mrHr^prr{fPVuN1+ z4=9}DkfKLYqUq7Q7@qa$)o6&2)kJx-3|go}k9HCI6ahL?NPA&khLUL}k_;mU&7GcN zNG6(xXW}(+a%IT80=-13-Q~sBo>$F2m`)7~wjW&XKndrz8soC*br=F*A_>Sh_Y}2Mt!#A1~2l?|hj) z9wpN&jISjW)?nl{@t`yuLviwvj)vyZQ4KR#mU-LE)mQ$yThO1oohRv;93oEXE8mYE zXPQSVCK~Lp3hIA_46A{8DdA+rguh@98p?VG2+Nw(4mu=W(sK<#S`IoS9nwuOM}C0) zH9U|6N=BXf!jJ#o;z#6vi=Y3NU5XT>ZNGe^z4u$i&x4ty^Sl;t_#`|^hmur~;r;o- z*CqJb?KWBoT`4`St5}10d*RL?!hm`GaFyxLMJPgbBvjVD??f7GU9*o?4!>NabqqR! z{BGK7%_}96G95B299eErE5_rkGmSWKP~590$HXvsRGJN5-%6d@=~Rs_68BLA1RkZb zD%ccBqGF0oGuZ?jbulkt!M}{S1;9gwAVkgdilT^_AS`w6?UH5Jd=wTUA-d$_O0DuM z|9E9XZFl$tZctd`Bq=OfI(cw4A)|t zl$W~3_RkP zFA6wSu+^efs79KH@)0~c3Dn1nSkNj_s)qBUGs6q?G0vjT&C5Y3ax-seA_+_}m`aj} zvW04)0TSIpqQkD@#NXZBg9z@GK1^ru*aKLrc4{J0PjhNfJT}J;vEeJ1ov?*KVNBy< zXtNIY3TqLZ=o1Byc^wL!1L6#i6n(088T9W<_iu~$S&VWGfmD|wNj?Q?Dnc#6iskoG zt^u26JqFnt=xjS-=|ACC%(=YQh{_alLW1tk;+tz1ujzeQ--lEu)W^Jk>UmHK(H303f}P2i zrsrQ*nEz`&{V!%2O446^8qLR~-Pl;2Y==NYj^B*j1vD}R5plk>%)GZSSjbi|tx>YM zVd@IS7b>&Uy%v==*35wGwIK4^iV{31mc)dS^LnN8j%#M}s%B@$=bPFI_ifcyPd4hilEWm71chIwfIR(-SeQaf20{;EF*(K(Eo+hu{}I zZkjXyF}{(x@Ql~*yig5lAq7%>-O5E++KSzEe(sqiqf1>{Em)pN`wf~WW1PntPpzKX zn;14G3FK7IQf!~n>Y=cd?=jhAw1+bwlVcY_kVuRyf!rSFNmR4fOc(g7(fR{ANvcO< zbG|cnYvKLa>dU(Z9YP796`Au?gz)Ys?w!af`F}1#W>x_O|k9Q z>#<6bKDt3Y}?KT2tmhU>H6Umn}J5M zarILVggiZs=kschc2TKib2`gl^9f|(37W93>80keUkrC3ok1q{;PO6HMbm{cZ^ROcT#tWWsQy?8qKWt<42BGryC(Dx>^ohIa0u7$^)V@Bn17^(VUgBD> zAr*Wl6UwQ&AAP%YZ;q2cZ;@2M(QeYFtW@PZ+mOO5gD1v-JzyE3^zceyE5H?WLW?$4 zhBP*+3i<09M$#XU;jwi7>}kW~v%9agMDM_V1$WlMV|U-Ldmr|<_nz*F_kcgrJnrViguEnJt{=Mk5f4Foin7(3vUXC>4gyJ>sK<;-p{h7 z2_mr&Fca!E^7R6VvodGznqJn3o)Ibd`gk>uKF7aemX*b~Sn#=NYl5j?v*T4FWZF2D zaX(M9hJ2YuEi%b~4?RkJwT*?aCRT@ecBkq$O!i}EJJEw`*++J_a>gsMo0CG^pZ3x+ zdfTSbCgRwtvAhL$p=iIf7%Vyb!j*UJsmOMler--IauWQ;(ddOk+U$WgN-RBle~v9v z9m2~@h|x*3t@m+4{U2}fKzRoVePrF-}U{`YT|vW?~64Bv*7|Dz03 zRYM^Yquhf*ZqkN?+NK4Ffm1;6BR0ZyW3MOFuV1ljP~V(=-tr^Tgu#7$`}nSd<8?cP z`VKtIz5$~InI0YnxAmn|pJZj+nPlI3zWsykXTKRnDCBm~Dy*m^^qTuY+8dSl@>&B8~0H$Y0Zc25APo|?R= z>_#h^kcfs#ae|iNe{BWA7K1mLuM%K!_V?fDyEqLkkT&<`SkEJ;E+Py^%hPVZ(%a2P4vL=vglF|X_`Z$^}q470V+7I4;UYdcZ7vU=41dd{d#KmI+|ZGa>C10g6w1a?wxAc&?iYsEv zuCwWvcw4FoG=Xrq=JNyPG*yIT@xbOeV`$s_kx`pH0DXPf0S7L?F208x4ET~j;yQ2c zhtq=S{T%82U7GxlUUKMf-NiuhHD$5*x{6}}_eZ8_kh}(}BxSPS9<(x2m$Rn0sx>)a zt$+qLRJU}0)5X>PXVxE?Jxpw(kD0W43ctKkj8DjpYq}lFZE98Je+v2t7uxuKV;p0l z5b9smYi5~k2%4aZe+~6HyobTQ@4_z#*lRHl# zSA`s~Jl@RGq=B3SNQF$+puBQv>DaQ--V!alvRSI~ZoOJx3VP4sbk!NdgMNBVbG&BX zdG*@)^g4#M#qoT`^NTR538vx~rdyOZcfzd7GBHl68-rG|fkofiGAXTJx~`~%a&boY zZ#M4sYwHIOnu-Mr!Ltpl8!NrX^p74tq{f_F4%M@&<=le;>xc5pAi&qn4P>04D$fp` z(OuJXQia--?vD0DIE6?HC|+DjH-?Cl|GqRKvs8PSe027_NH=}+8km9Ur8(JrVx@*x z0lHuHd=7*O+&AU_B;k{>hRvV}^Uxl^L1-c-2j4V^TG?2v66BRxd~&-GMfcvKhWgwu z60u{2)M{ZS)r*=&J4%z*rtqs2syPiOQq(`V0UZF)boPOql@E0U39>d>MP=BqFeJzz zh?HDKtY3%mR~reR7S2rsR0aDMA^a|L^_*8XM9KjabpYSBu z;zkfzU~12|X_W_*VNA=e^%Za14PMOC!z`5Xt|Fl$2bP9fz>(|&VJFZ9{z;;eEGhOl zl7OqqDJzvgZvaWc7Nr!5lfl*Qy7_-fy9%f(v#t#&2#9o-ba%J3(%s#C=@dagx*I{d zB&AzGT9EEiknWJU^naNdz7Logo%#OFV!eyCIQuzgpZDDN-1F}JJTdGXiLN85p|GT! zGOfNd8^RD;MsK*^3gatg2#W0J<8j)UCkUYoZRR|R*UibOm-G)S#|(`$hPA7UmH+fT ziZxTgeiR_yzvNS1s+T!xw)QgNSH(_?B@O?uTBwMj`G)2c^8%g8zu zxMu5SrQ^J+K91tkPrP%*nTpyZor#4`)}(T-Y8eLd(|sv8xcIoHnicKyAlQfm1YPyI z!$zimjMlEcmJu?M6z|RtdouAN1U5lKmEWY3gajkPuUHYRvTVeM05CE@`@VZ%dNoZN z>=Y3~f$~Gosud$AN{}!DwV<6CHm3TPU^qcR!_0$cY#S5a+GJU-2I2Dv;ktonSLRRH zALlc(lvX9rm-b5`09uNu904c}sU(hlJZMp@%nvkcgwkT;Kd7-=Z_z9rYH@8V6Assf zKpXju&hT<=x4+tCZ{elYtH+_F$V=tq@-`oC%vdO>0Wmu#w*&?_=LEWRJpW|spYc8V z=$)u#r}Pu7kvjSuM{FSyy9_&851CO^B zTm$`pF+lBWU!q>X#;AO1&=tOt=i!=9BVPC#kPJU}K$pO&8Ads)XOFr336_Iyn z$d{MTGYQLX9;@mdO;_%2Ayw3hv}_$UT00*e{hWxS?r=KT^ymEwBo429b5i}LFmSk` zo)-*bF1g;y@&o=34TW|6jCjUx{55EH&DZ?7wB_EmUg*B4zc6l7x-}qYLQR@^7o6rrgkoujRNym9O)K>wNfvY+uy+4Om{XgRHi#Hpg*bZ36_X%pP`m7FIF z?n?G*g&>kt$>J_PiXIDzgw3IupL3QZbysSzP&}?JQ-6TN-aEYbA$X>=(Zm}0{hm6J zJnqQnEFCZGmT06LAdJ^T#o`&)CA*eIYu?zzDJi#c$1H9zX}hdATSA|zX0Vb^q$mgg z&6kAJ=~gIARct>}4z&kzWWvaD9#1WK=P>A_aQxe#+4cpJtcRvd)TCu! z>eqrt)r(`qYw6JPKRXSU#;zYNB7a@MYoGuAT0Nzxr`>$=vk`uEq2t@k9?jYqg)MXl z67MA3^5_}Ig*mycsGeH0_VtK3bNo;8#0fFQ&qDAj=;lMU9%G)&HL>NO|lWU3z+m4t7 zfV*3gSuZ++rIWsinX@QaT>dsbD>Xp8%8c`HLamm~(i{7L&S0uZ;`W-tqU4XAgQclM$PxE76OH(PSjHjR$(nh({vsNnawhP!!HcP!l)5 zG;C=k0xL<^q+4rpbp{sGzcc~ZfGv9J*k~PPl}e~t$>WPSxzi0}05(D6d<=5+E}Y4e z@_QZtDcC7qh4#dQFYb6Pulf_8iAYYE z1SWJfNe5@auBbE5O=oeO@o*H5mS(pm%$!5yz-71~lEN5=x0eN|V`xAeP;eTje?eC= z53WneK;6n35{OaIH2Oh6Hx)kV-jL-wMzFlynGI8Wk_A<~_|06rKB#Pi_QY2XtIGW_ zYr)RECK_JRzR1tMd(pM(L=F98y~7wd4QBKAmFF(AF(e~+80$GLZpFc;a{kj1h}g4l z3SxIRlV=h%Pl1yRacl^g>9q%>U+`P(J`oh-w8i82mFCn|NJ5oX*^VKODX2>~HLUky z3D(ak0Sj=Kv^&8dUhU(3Ab!U5TIy97PKQ))&`Ml~hik%cHNspUpCn24cqH@dq6ZVo zO9xz!cEMm;NL;#z-tThlFF%=^ukE8S0;hDMR_`rv#eTYg7io1w9n_vJpK+6%=c#Y?wjAs_(#RQA0gr&Va2BQTq` zUc8)wHEDl&Uyo<>-PHksM;b-y(`E_t8Rez@Iw+eogcEI*FDg@Bc;;?3j3&kPsq(mx z+Yr_J#?G6D?t2G%O9o&e7Gbf&>#(-)|8)GIbG_a${TU26cVrIQSt=% zQ~XY-b1VQVc>IV=7um0^Li>dF z`zSm_o*i@ra4B+Tw5jdguVqx`O(f4?_USIMJzLvS$*kvBfEuToq-VR%K*%1VHu=++ zQ`=cG3cCnEv{ZbP-h9qbkF}%qT$j|Z7ZB2?s7nK@gM{bAD=eoDKCCMlm4LG~yre!- zzPP#Rn9ZDUgb4++M78-V&VX<1ah(DN z(4O5b`Fif%*k?L|t%!WY`W$C_C`tzC`tI7XC`->oJs_Ezs=K*O_{*#SgNcvYdmBbG zHd8!UTzGApZC}n7LUp1fe0L<3|B5GdLbxX@{ETeUB2vymJgWP0q2E<&!Dtg4>v`aa zw(QcLoA&eK{6?Rb&6P0kY+YszBLXK49i~F!jr)7|xcnA*mOe1aZgkdmt4{Nq2!!SL z`aD{6M>c00muqJt4$P+RAj*cV^vn99UtJ*s${&agQ;C>;SEM|l%KoH_^kAcmX=%)* zHpByMU_F12iGE#68rHGAHO_ReJ#<2ijo|T7`{PSG)V-bKw}mpTJwtCl%cq2zxB__m zM_p2k8pDmwA*$v@cmm>I)TW|7a7ng*X7afyR1dcuVGl|BQzy$MM+zD{d~n#)9?1qW zdk(th4Ljb-vpv5VUt&9iuQBnQ$JicZ)+HoL`&)B^Jr9F1wvf=*1and~v}3u{+7u7F zf0U`l4Qx-ANfaB3bD1uIeT^zeXerps8nIW(tmIxYSL;5~!&&ZOLVug2j4t7G=zzK+ zmPy5<4h%vq$Fw)i1)ya{D;GyEm3fybsc8$=$`y^bRdmO{XU#95EZ$I$bBg)FW#=}s z@@&c?xwLF3|C7$%>}T7xl0toBc6N^C{!>a8vWc=G!bAFKmn{AKS6RxOWIJBZXP&0CyXAiHd?7R#S46K6UXYXl#c_#APL5SfW<<-|rcfX&B6e*isa|L^RK=0}D`4q-T0VAs0 zToyrF6`_k$UFGAGhY^&gg)(Fq0p%J{h?E)WQ(h@Gy=f6oxUSAuT4ir}jI)36|NnmnI|vtij;t!jT?6Jf-E19}9Lf9(+N+ z)+0)I5mST_?3diP*n2=ZONTYdXkjKsZ%E$jjU@0w_lL+UHJOz|K{{Uh%Zy0dhiqyh zofWXzgRyFzY>zpMC8-L^43>u#+-zlaTMOS(uS!p{Jw#u3_9s)(s)L6j-+`M5sq?f+ zIIcjq$}~j9b`0_hIz~?4?b(Sqdpi(;1=8~wkIABU+APWQdf5v@g=1c{c{d*J(X5+cfEdG?qxq z{GKkF;)8^H&Xdi~fb~hwtJRsfg#tdExEuDRY^x9l6=E+|fxczIW4Z29NS~-oLa$Iq z93;5$(M0N8ba%8&q>vFc=1}a8T?P~_nrL5tYe~X>G=3QoFlBae8vVt-K!^@vusN<8gQJ!WD7H%{*YgY0#(tXxXy##C@o^U7ysxe zLmUWN@4)JBjjZ3G-_)mrA`|NPCc8Oe!%Ios4$HWpBmJse7q?)@Xk%$x&lIY>vX$7L zpfNWlXxy2p7TqW`Wq22}Q3OC2OWTP_X(*#kRx1WPe%}$C!Qn^FvdYmvqgk>^nyk;6 zXv*S#P~NVx1n6pdbXuX9x_}h1SY#3ZyvLZ&VnWVva4)9D|i7kjGY{>am&^ z-_x1UYM1RU#z17=AruK~{BK$A65Sajj_OW|cpYQBGWO*xfGJXSn4E&VMWchq%>0yP z{M2q=zx!VnO71gb8}Al2i+uxb=ffIyx@oso@8Jb88ld6M#wgXd=WcX$q$91o(94Ek zjeBqQ+CZ64hI>sZ@#tjdL}JeJu?GS7N^s$WCIzO`cvj60*d&#&-BQ>+qK#7l+!u1t zBuyL-Cqups?2>)ek2Z|QnAqs_`u1#y8=~Hvsn^2Jtx-O`limc*w;byk^2D-!*zqRi zVcX+4lzwcCgb+(lROWJ~qi;q2!t6;?%qjGcIza=C6{T7q6_?A@qrK#+)+?drrs3U}4Fov+Y}`>M z#40OUPpwpaC-8&q8yW0XWGw`RcSpBX+7hZ@xarfCNnrl-{k@`@Vv> zYWB*T=4hLJ1SObSF_)2AaX*g(#(88~bVG9w)ZE91eIQWflNecYC zzUt}ov<&)S&i$}?LlbIi9i&-g=UUgjWTq*v$!0$;8u&hwL*S^V!GPSpM3PR3Ra5*d z7d77UC4M{#587NcZS4+JN=m#i)7T0`jWQ{HK3rIIlr3cDFt4odV25yu9H1!}BVW-& zrqM5DjDzbd^pE^Q<-$1^_tX)dX8;97ILK{ z!{kF{!h`(`6__+1UD5=8sS&#!R>*KqN9_?(Z$4cY#B)pG8>2pZqI;RiYW6aUt7kk*s^D~Rml_fg$m+4+O5?J&p1)wE zp5L-X(6og1s(?d7X#l-RWO+5Jj(pAS{nz1abM^O;8hb^X4pC7ADpzUlS{F~RUoZp^ zuJCU_fq}V!9;knx^uYD2S9E`RnEsyF^ZO$;`8uWNI%hZzKq=t`q12cKEvQjJ9dww9 zCerpM3n@Ag+XZJztlqHRs!9X(Dv&P;_}zz$N&xwA@~Kfnd3}YiABK*T)Ar2E?OG6V z<;mFs`D?U7>Rradv7(?3oCZZS_0Xr#3NNkpM1@qn-X$;aNLYL;yIMX4uubh^Xb?HloImt$=^s8vm)3g!{H1D|k zmbg_Rr-ypQokGREIcG<8u(=W^+oxelI&t0U`dT=bBMe1fl+9!l&vEPFFu~yAu!XIv4@S{;| z8?%<1@hJp%7AfZPYRARF1hf`cq_VFQ-y74;EdMob{z&qec2hiQJOQa>f-?Iz^VXOr z-wnfu*uT$(5WmLsGsVkHULPBvTRy0H(}S0SQ18W0kp_U}8Phc3gz!Hj#*VYh$AiDE245!YA0M$Q@rM zT;}1DQ}MxV<)*j{hknSHyihgMPCK=H)b-iz9N~KT%<&Qmjf39L@&7b;;>9nQkDax- zk%7ZMA%o41l#(G5K=k{D{80E@P|I;aufYpOlIJXv!dS+T^plIVpPeZ)Gp`vo+?BWt z8U8u=C51u%>yDCWt>`VGkE5~2dD4y_8+n_+I9mFN(4jHJ&x!+l*>%}b4Z>z#(tb~< z+<+X~GIi`sDb=SI-7m>*krlqE3aQD?D5WiYX;#8m|ENYKw}H^95u!=n=xr3jxhCB&InJ7>zgLJg;i?Sjjd`YW!2; z%+y=LwB+MMnSGF@iu#I%!mvt)aXzQ*NW$cHNHwjoaLtqKCHqB}LW^ozBX?`D4&h%# zeMZ3ZumBn}5y9&odo3=hN$Q&SRte*^-SNZg2<}6>OzRpF91oy0{RuZU(Q0I zvx%|9>;)-Ca9#L)HQt~axu0q{745Ac;s1XQKV ze3D9I5gV5SP-J>&3U!lg1`HN>n5B6XxYpwhL^t0Z)4$`YK93vTd^7BD%<)cIm|4e!;*%9}B-3NX+J*Nr@;5(27Zmf(TmfHsej^Bz+J1 zXKIjJ)H{thL4WOuro|6&aPw=-JW8G=2 z|L4YL)^rYf7J7DOKXpTX$4$Y{-2B!jT4y^w8yh3LKRKO3-4DOshFk}N^^Q{r(0K0+ z?7w}x>(s{Diq6K)8sy)>%*g&{u>)l+-Lg~=gteW?pE`B@FE`N!F-+aE;XhjF+2|RV z8vV2((yeA-VDO;3=^E;fhW~b=Wd5r8otQrO{Vu)M1{j(+?+^q%xpYCojc6rmQ<&ytZ2ly?bw*X)WB8(n^B4Gmxr^1bQ&=m;I4O$g{ z3m|M{tmkOyAPnMHu(Z}Q1X1GM|A+)VDP3Fz934zSl)z>N|D^`G-+>Mej|VcK+?iew zQ3=DH4zz;i>z{Yv_l@j*?{936kxM{c7eK$1cf8wxL>>O#`+vsu*KR)te$adfTD*w( zAStXnZk<6N3V-Vs#GB%vXZat+(EFWbkbky#{yGY`rOvN)?{5qUuFv=r=dyYZrULf%MppWuNRUWc z8|YaIn}P0DGkwSZ(njAO$Zhr3Yw`3O1A+&F*2UjO{0`P%kK(qL;kEkfjRC=lxPRjL z{{4PO3-*5RZ_B3LUB&?ZpJ4nk1E4L&eT~HX0Jo(|uGQCW3utB@p)rF@W*n$==TlS zKiTfzhrLbAeRqru%D;fUwXOUcHud{pw@Ib1xxQ}<2)?KC&%y5PVef<7rcu2l!8dsy z?lvdaHJ#s$0m18y{x#fB$o=l)-sV?Qya5GWf#8Vd{~Grn@qgX#!EI`Y>++l%1A;eL z{_7t6jMeEr@a+oxyCL^+_}9Qc;i0&Xd%LXp?to*R|26LKHG(m0)*QF4*h;5%YG5<9)c> z1vq!7bIJSv1^27i-mcH!zX>ep3Iw0^{nx<1jOy)N_UoFD8v}x~2mEWapI3m~kMQkR z#&@4FuEGBn`mgtSx6jeY7vUQNf=^}sTZErIEpH!cy|@7Z zU4h_Oxxd2s=f{}$XXy4}%JqTSjRC + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('./service-worker.js').then(function() { + console.log('Service Worker Registered'); + }); + } + +``` + +Note: workbox creates the respective service worker and dynamically generate the `service-worker.js` + +### Managing dependencies + +For example, to add [Leaflet][] library as a runtime dependency of your application, you would run following command: + + npm install --save --save-exact leaflet + +To benefit from TypeScript type definitions from [DefinitelyTyped][] repository in development, you would run following command: + + npm install --save-dev --save-exact @types/leaflet + +Then you would import the JS and CSS files specified in library's installation instructions so that [Webpack][] knows about them: +Edit [src/main/webapp/app/vendor.ts](src/main/webapp/app/vendor.ts) file: + +``` +import 'leaflet/dist/leaflet.js'; +``` + +Edit [src/main/webapp/content/css/vendor.css](src/main/webapp/content/css/vendor.css) file: + +``` +@import '~leaflet/dist/leaflet.css'; +``` + +Note: there are still few other things remaining to do for Leaflet that we won't detail here. + +For further instructions on how to develop with JHipster, have a look at [Using JHipster in development][]. + +### Using angular-cli + +You can also use [Angular CLI][] to generate some custom client code. + +For example, the following command: + + ng generate component my-component + +will generate few files: + + create src/main/webapp/app/my-component/my-component.component.html + create src/main/webapp/app/my-component/my-component.component.ts + update src/main/webapp/app/app.module.ts + +## Building for production + +To optimize the Bookstore application for production, run: + + ./mvnw -Pprod clean package + +This will concatenate and minify the client CSS and JavaScript files. It will also modify `index.html` so it references these new files. +To ensure everything worked, run: + + java -jar target/*.war + +Then navigate to [http://localhost:8080](http://localhost:8080) in your browser. + +Refer to [Using JHipster in production][] for more details. + +## Testing + +To launch your application's tests, run: + + ./mvnw clean test + +### Client tests + +Unit tests are run by [Jest][] and written with [Jasmine][]. They're located in [src/test/javascript/](src/test/javascript/) and can be run with: + + npm test + +For more information, refer to the [Running tests page][]. + +### Code quality + +Sonar is used to analyse code quality. You can start a local Sonar server (accessible on http://localhost:9001) with: + +``` +docker-compose -f src/main/docker/sonar.yml up -d +``` + +Then, run a Sonar analysis: + +``` +./mvnw -Pprod clean test sonar:sonar +``` + +For more information, refer to the [Code quality page][]. + +## Using Docker to simplify development (optional) + +You can use Docker to improve your JHipster development experience. A number of docker-compose configuration are available in the [src/main/docker](src/main/docker) folder to launch required third party services. + +For example, to start a mysql database in a docker container, run: + + docker-compose -f src/main/docker/mysql.yml up -d + +To stop it and remove the container, run: + + docker-compose -f src/main/docker/mysql.yml down + +You can also fully dockerize your application and all the services that it depends on. +To achieve this, first build a docker image of your app by running: + + ./mvnw package -Pprod verify jib:dockerBuild + +Then run: + + docker-compose -f src/main/docker/app.yml up -d + +For more information refer to [Using Docker and Docker-Compose][], this page also contains information on the docker-compose sub-generator (`jhipster docker-compose`), which is able to generate docker configurations for one or several JHipster applications. + +## Continuous Integration (optional) + +To configure CI for your project, run the ci-cd sub-generator (`jhipster ci-cd`), this will let you generate configuration files for a number of Continuous Integration systems. Consult the [Setting up Continuous Integration][] page for more information. + +[jhipster homepage and latest documentation]: https://www.jhipster.tech +[jhipster 5.8.2 archive]: https://www.jhipster.tech/documentation-archive/v5.8.2 +[using jhipster in development]: https://www.jhipster.tech/documentation-archive/v5.8.2/development/ +[using docker and docker-compose]: https://www.jhipster.tech/documentation-archive/v5.8.2/docker-compose +[using jhipster in production]: https://www.jhipster.tech/documentation-archive/v5.8.2/production/ +[running tests page]: https://www.jhipster.tech/documentation-archive/v5.8.2/running-tests/ +[code quality page]: https://www.jhipster.tech/documentation-archive/v5.8.2/code-quality/ +[setting up continuous integration]: https://www.jhipster.tech/documentation-archive/v5.8.2/setting-up-ci/ +[node.js]: https://nodejs.org/ +[yarn]: https://yarnpkg.org/ +[webpack]: https://webpack.github.io/ +[angular cli]: https://cli.angular.io/ +[browsersync]: http://www.browsersync.io/ +[jest]: https://facebook.github.io/jest/ +[jasmine]: http://jasmine.github.io/2.0/introduction.html +[protractor]: https://angular.github.io/protractor/ +[leaflet]: http://leafletjs.com/ +[definitelytyped]: http://definitelytyped.org/ diff --git a/jhipster-5/bookstore-monolith/angular.json b/jhipster-5/bookstore-monolith/angular.json new file mode 100644 index 0000000000..61791db9fb --- /dev/null +++ b/jhipster-5/bookstore-monolith/angular.json @@ -0,0 +1,39 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "bookstore": { + "root": "", + "sourceRoot": "src/main/webapp", + "projectType": "application", + "architect": {} + } + }, + "defaultProject": "bookstore", + "cli": { + "packageManager": "npm" + }, + "schematics": { + "@schematics/angular:component": { + "inlineStyle": true, + "inlineTemplate": false, + "spec": false, + "prefix": "jhi", + "styleExt": "scss" + }, + "@schematics/angular:directive": { + "spec": false, + "prefix": "jhi" + }, + "@schematics/angular:guard": { + "spec": false + }, + "@schematics/angular:pipe": { + "spec": false + }, + "@schematics/angular:service": { + "spec": false + } + } +} diff --git a/jhipster-5/bookstore-monolith/mvnw b/jhipster-5/bookstore-monolith/mvnw new file mode 100755 index 0000000000..5551fde8e7 --- /dev/null +++ b/jhipster-5/bookstore-monolith/mvnw @@ -0,0 +1,286 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + wget "$jarUrl" -O "$wrapperJarPath" + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + curl -o "$wrapperJarPath" "$jarUrl" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/jhipster-5/bookstore-monolith/mvnw.cmd b/jhipster-5/bookstore-monolith/mvnw.cmd new file mode 100644 index 0000000000..e5cfb0ae9e --- /dev/null +++ b/jhipster-5/bookstore-monolith/mvnw.cmd @@ -0,0 +1,161 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" +FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + echo Found %WRAPPER_JAR% +) else ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" + echo Finished downloading %WRAPPER_JAR% +) +@REM End of extension + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/jhipster-5/bookstore-monolith/package-lock.json b/jhipster-5/bookstore-monolith/package-lock.json new file mode 100644 index 0000000000..6e2a8dc526 --- /dev/null +++ b/jhipster-5/bookstore-monolith/package-lock.json @@ -0,0 +1,18244 @@ +{ + "name": "bookstore", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.13.1.tgz", + "integrity": "sha512-QDmIbqde75ZZSEFbw6Q6kQWq4cY6C7D67yujXw6XTyubDNAs1tyXJyxTIB8vjSlEKwRizTTDd/B0ZXVcke3Mvw==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.1", + "rxjs": "6.3.3" + }, + "dependencies": { + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular-devkit/core": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.1.tgz", + "integrity": "sha512-56XDWWfIzOAkEk69lBLgmCYybPUA4yjunhmMlCk7vVdb7gbQUyzNjFD04Uj0GjlejatAQ5F76tRwygD9C+3RXQ==", + "dev": true, + "requires": { + "ajv": "6.7.0", + "chokidar": "2.0.4", + "fast-json-stable-stringify": "2.0.0", + "rxjs": "6.3.3", + "source-map": "0.7.3" + }, + "dependencies": { + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular-devkit/schematics": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.3.1.tgz", + "integrity": "sha512-cd7usiasfSgw75INz72/VssrLr9tiVRYfo1TEdvr9ww0GuQbuQpB33xbV8W135eAV8+wzQ3Ce8ohaDHibvj6Yg==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.1", + "rxjs": "6.3.3" + }, + "dependencies": { + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@angular/cli": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-7.3.1.tgz", + "integrity": "sha512-8EvXYRhTqTaTk5PKv7VZxIWJiyG51R9RC9gtpRFx4bbnurqBHdEUxGMmaRsGT8QDbfvVsWnuakE0eeW1CrfZAQ==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.13.1", + "@angular-devkit/core": "7.3.1", + "@angular-devkit/schematics": "7.3.1", + "@schematics/angular": "7.3.1", + "@schematics/update": "0.13.1", + "@yarnpkg/lockfile": "1.1.0", + "ini": "1.3.5", + "inquirer": "6.2.1", + "npm-package-arg": "6.1.0", + "opn": "5.4.0", + "pacote": "9.4.0", + "semver": "5.6.0", + "symbol-observable": "1.2.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "inquirer": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz", + "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.0", + "figures": "^2.0.0", + "lodash": "^4.17.10", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.1.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.0.0", + "through": "^2.3.6" + } + }, + "opn": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@angular/common": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.4.tgz", + "integrity": "sha512-3/i8RtnLTx/90gJHk5maE8zwsSiHgHvLItaa0qVfNlWiU0eCId/PL6TgDkut5vN9SQYL0oxhxFaVd35HmwsmuQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.4.tgz", + "integrity": "sha512-+zyMzPCL45ePEV9nrnYJvhAVgp2Y19bDaq0f0YdZAqAjgDqHzXGGR6wX8GueyJWmUYWx5vwK6Apla4HwDrYA1w==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler-cli": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.2.4.tgz", + "integrity": "sha512-UhLosSeuwFIfaGqGcYOh9WSOuzEpeuhIRAOt81MeqOQEqkoreUjfxrQq8XWNkdqsPZHtiptF5ZwXlMBxlj9jJg==", + "dev": true, + "requires": { + "canonical-path": "1.0.0", + "chokidar": "^1.4.2", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.7.2", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "shelljs": "^0.8.1", + "source-map": "^0.6.1", + "tslib": "^1.9.0", + "yargs": "9.0.1" + }, + "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@angular/core": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.4.tgz", + "integrity": "sha512-kfAxhIxl89PmB7y81FR/RAv0yWRFcEYxEnTwV+o8jKGfemAXtQ0g/Vh+lJR0SD/TBgFilMxotN1mhwH4A8GShw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/forms": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.2.4.tgz", + "integrity": "sha512-DAtOrdlTRsgvmZrsvczCAkY8dhTwZb5DXBmPuSXh0UR9lvEiCgNHGbwEiIiIkAHpw1wSeXZrq0qyy/oJRvf18g==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/platform-browser": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.2.4.tgz", + "integrity": "sha512-Klt8aKR5SP9bqfMfpSY5vQOY7AQEs8JGuZOk5Bfc2dUtYT2IEIvK2IqO8v2rcFRVO13HOPUxl328efyHqLgI7g==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.4.tgz", + "integrity": "sha512-J/xWlmaYOPUoCHZ5TiIRiyYa4uRMtCz3aGdBfY8k/NWtNo8SCYaS3aut7Sk4RS5rK8aAVi+aYFlY5YOrlW+Hbg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/router": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.2.4.tgz", + "integrity": "sha512-T8Uqf2H1SV1MQI38WwYJ4aa+4NNnvlp2Tp/rkfg6tKcp/cLkKqE6OOfiy9lmW+i/624v8tMgYoBMOUNBjAG23g==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.3.4.tgz", + "integrity": "sha512-jRsuseXBo9pN197KnDwhhaaBzyZr2oIcLHHTt2oDdQrej5Qp57dCCJafWx5ivU8/alEYDpssYqv1MUqcxwQlrA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.3.4", + "@babel/helpers": "^7.2.0", + "@babel/parser": "^7.3.4", + "@babel/template": "^7.2.2", + "@babel/traverse": "^7.3.4", + "@babel/types": "^7.3.4", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.4.tgz", + "integrity": "sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==", + "dev": true, + "requires": { + "@babel/types": "^7.3.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helpers": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.3.1.tgz", + "integrity": "sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA==", + "dev": true, + "requires": { + "@babel/template": "^7.1.2", + "@babel/traverse": "^7.1.5", + "@babel/types": "^7.3.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.4.tgz", + "integrity": "sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==", + "dev": true + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/runtime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", + "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.12.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "dev": true + } + } + }, + "@babel/template": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.3.4.tgz", + "integrity": "sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.3.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.3.4", + "@babel/types": "^7.3.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz", + "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@fortawesome/angular-fontawesome": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.3.0.tgz", + "integrity": "sha512-wXvyPI7GidoNiqeMz2re9iemUMFH4zBmuv94CfXlaanQ8+kMP/fYs/k69PLVN1KsebQY4kRA9GHmc1U1ndBkJg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@fortawesome/fontawesome-common-types": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.15.tgz", + "integrity": "sha512-ATBRyKJw1d2ko+0DWN9+BXau0EK3I/Q6pPzPv3LhJD7r052YFAkAdfb1Bd7ZqhBsJrdse/S7jKxWUOZ61qBD4g==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.14.tgz", + "integrity": "sha512-T1qCqkwm9PuvK53J64D1ovfrOTa1kG+SrHNj5cFst/rrskhCnbxpRdbqFIdc/thmXC0ebBX8nOUyja2/mrxe4g==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.14" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.7.1.tgz", + "integrity": "sha512-5V/Q+JoPzuiIHW2JwmZGvE9bHguvNJKa7611DPo51uIvYv9LweX/SnDF+HC23X2W5T3myHhnGi+EZJTmidAmyg==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.14" + } + }, + "@iamstarkov/listr-update-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@iamstarkov/listr-update-renderer/-/listr-update-renderer-0.4.1.tgz", + "integrity": "sha512-IJyxQWsYDEkf8C8QthBn5N8tIUR9V9je6j3sMIpAkonaadjbvxmRC6RAhpa3RKxndhNnU2M6iNbtJwd7usQYIA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + } + } + }, + "@jest/console": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.3.0.tgz", + "integrity": "sha512-NaCty/OOei6rSDcbPdMiCbYCI0KGFGPgGO6B09lwWt5QTxnkuhKYET9El5u5z1GAcSxkQmSMtM63e24YabCWqA==", + "dev": true, + "requires": { + "@jest/source-map": "^24.3.0", + "@types/node": "*", + "chalk": "^2.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/core": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.5.0.tgz", + "integrity": "sha512-RDZArRzAs51YS7dXG1pbXbWGxK53rvUu8mCDYsgqqqQ6uSOaTjcVyBl2Jce0exT2rSLk38ca7az7t2f3b0/oYQ==", + "dev": true, + "requires": { + "@jest/console": "^24.3.0", + "@jest/reporters": "^24.5.0", + "@jest/test-result": "^24.5.0", + "@jest/transform": "^24.5.0", + "@jest/types": "^24.5.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.5.0", + "jest-config": "^24.5.0", + "jest-haste-map": "^24.5.0", + "jest-message-util": "^24.5.0", + "jest-regex-util": "^24.3.0", + "jest-resolve-dependencies": "^24.5.0", + "jest-runner": "^24.5.0", + "jest-runtime": "^24.5.0", + "jest-snapshot": "^24.5.0", + "jest-util": "^24.5.0", + "jest-validate": "^24.5.0", + "jest-watcher": "^24.5.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/environment": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.5.0.tgz", + "integrity": "sha512-tzUHR9SHjMXwM8QmfHb/EJNbF0fjbH4ieefJBvtwO8YErLTrecc1ROj0uo2VnIT6SlpEGZnvdCK6VgKYBo8LsA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.5.0", + "@jest/transform": "^24.5.0", + "@jest/types": "^24.5.0", + "@types/node": "*", + "jest-mock": "^24.5.0" + } + }, + "@jest/fake-timers": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.5.0.tgz", + "integrity": "sha512-i59KVt3QBz9d+4Qr4QxsKgsIg+NjfuCjSOWj3RQhjF5JNy+eVJDhANQ4WzulzNCHd72srMAykwtRn5NYDGVraw==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0", + "@types/node": "*", + "jest-message-util": "^24.5.0", + "jest-mock": "^24.5.0" + } + }, + "@jest/reporters": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.5.0.tgz", + "integrity": "sha512-vfpceiaKtGgnuC3ss5czWOihKOUSyjJA4M4udm6nH8xgqsuQYcyDCi4nMMcBKsHXWgz9/V5G7iisnZGfOh1w6Q==", + "dev": true, + "requires": { + "@jest/environment": "^24.5.0", + "@jest/test-result": "^24.5.0", + "@jest/transform": "^24.5.0", + "@jest/types": "^24.5.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-api": "^2.1.1", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-source-maps": "^3.0.1", + "jest-haste-map": "^24.5.0", + "jest-resolve": "^24.5.0", + "jest-runtime": "^24.5.0", + "jest-util": "^24.5.0", + "jest-worker": "^24.4.0", + "node-notifier": "^5.2.1", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@jest/source-map": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.3.0.tgz", + "integrity": "sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "callsites": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", + "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jest/test-result": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.5.0.tgz", + "integrity": "sha512-u66j2vBfa8Bli1+o3rCaVnVYa9O8CAFZeqiqLVhnarXtreSXG33YQ6vNYBogT7+nYiFNOohTU21BKiHlgmxD5A==", + "dev": true, + "requires": { + "@jest/console": "^24.3.0", + "@jest/types": "^24.5.0", + "@types/istanbul-lib-coverage": "^1.1.0" + } + }, + "@jest/transform": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.5.0.tgz", + "integrity": "sha512-XSsDz1gdR/QMmB8UCKlweAReQsZrD/DK7FuDlNo/pE8EcKMrfi2kqLRk8h8Gy/PDzgqJj64jNEzOce9pR8oj1w==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.5.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.5.0", + "jest-regex-util": "^24.3.0", + "jest-util": "^24.5.0", + "micromatch": "^3.1.10", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "@jest/types": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.5.0.tgz", + "integrity": "sha512-kN7RFzNMf2R8UDadPOl6ReyI+MT8xfqRuAnuVL+i4gwjv/zubdDK+EDeLHYwq1j0CSSR2W/MmgaRlMZJzXdmVA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^1.1.0", + "@types/yargs": "^12.0.9" + } + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@ng-bootstrap/ng-bootstrap": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-4.0.2.tgz", + "integrity": "sha512-SBsN8ORvj/WXpZGSyR2+CRkg6GCtax5+fsLKt9ImHKUVWwePVqRxiGlnxXqwNPHQ46vOdd7nDN9cwE7dfbGaAQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@ngtools/webpack": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.3.1.tgz", + "integrity": "sha512-EGQRjgDf5XP+Fm1MdZNRFiPd9e1vhl11BhjkwqkAsewic4eoz6fqXfj/Osz1hQy8xU+2dPPf/byQ/+nY3E02Zg==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.1", + "enhanced-resolve": "4.1.0", + "rxjs": "6.3.3", + "tree-kill": "1.2.1", + "webpack-sources": "1.3.0" + }, + "dependencies": { + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@ngx-translate/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-11.0.1.tgz", + "integrity": "sha512-nBCa1ZD9fAUY/3eskP3Lql2fNg8OMrYIej1/5GRsfcutx9tG/5fZLCv9m6UCw1aS+u4uK/vXjv1ctG/FdMvaWg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@ngx-translate/http-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-4.0.0.tgz", + "integrity": "sha512-x8LumqydWD7eX9yQTAVeoCM9gFUIGVTUjZqbxdAUavAA3qVnk9wCQux7iHLPXpydl8vyQmLoPQR+fFU+DUDOMA==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, + "@schematics/angular": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-7.3.1.tgz", + "integrity": "sha512-0Ne8APPlTAjKg5CSZqluwCuW/5yPjr3ALCWzqwPxN0suE745usThtasBmqrjw0RMIt8nRqRgtg54Z7lCPO9ZFg==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.1", + "@angular-devkit/schematics": "7.3.1", + "typescript": "3.2.4" + } + }, + "@schematics/update": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.13.1.tgz", + "integrity": "sha512-EHOqolT/d/jRGuVTCUESLpk8JNpuaPlsVHfeK7Kdp/t0wSEnmtOelZX4+leS25lGXDaDUF3138ntjrZR4n6bGw==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.1", + "@angular-devkit/schematics": "7.3.1", + "@yarnpkg/lockfile": "1.1.0", + "ini": "1.3.5", + "pacote": "9.4.0", + "rxjs": "6.3.3", + "semver": "5.6.0", + "semver-intersect": "1.4.0" + }, + "dependencies": { + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } + } + }, + "@types/babel__core": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.0.tgz", + "integrity": "sha512-wJTeJRt7BToFx3USrCDs2BhEi4ijBInTQjOIukj6a/5tEkwpFMVZ+1ppgmE+Q/FQyc5P/VWUbx7I9NELrKruHA==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.0.2.tgz", + "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.6.tgz", + "integrity": "sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/istanbul-lib-coverage": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz", + "integrity": "sha512-ohkhb9LehJy+PA40rDtGAji61NCgdtKLAlFoYp4cnuuQEswwdK3vz9SOIkkyc3wrk8dzjphQApNs56yyXLStaQ==", + "dev": true + }, + "@types/jest": { + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.0.tgz", + "integrity": "sha512-kOafJnUTnMd7/OfEO/x3I47EHswNjn+dbz9qk3mtonr1RvKT+1FGVxnxAx08I9K8Tl7j9hpoJRE7OCf+t10fng==", + "dev": true + }, + "@types/node": { + "version": "10.12.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.24.tgz", + "integrity": "sha512-GWWbvt+z9G5otRBW8rssOFgRY87J9N/qbhqfjMZ+gUuL6zoL+Hm6gP/8qQBG4jjimqdaNLCehcVapZ/Fs2WjCQ==", + "dev": true + }, + "@types/q": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", + "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", + "dev": true + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/yargs": { + "version": "12.0.10", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.10.tgz", + "integrity": "sha512-WsVzTPshvCSbHThUduGGxbmnwcpkgSctHGHTqzWyFg4lYAuV5qXlyFPOsP3OWqCINfmg/8VXP+zJaa4OxEsBQQ==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", + "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", + "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", + "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", + "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", + "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.7.11" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", + "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", + "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", + "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", + "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", + "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", + "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/utf8": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", + "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", + "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/helper-wasm-section": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-opt": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "@webassemblyjs/wast-printer": "1.7.11" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", + "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", + "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", + "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", + "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/floating-point-hex-parser": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-code-frame": "1.7.11", + "@webassemblyjs/helper-fsm": "1.7.11", + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", + "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11", + "@xtuc/long": "4.2.1" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", + "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", + "dev": true + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "dev": true + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "dev": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz", + "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==", + "dev": true + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "angular-router-loader": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/angular-router-loader/-/angular-router-loader-0.8.5.tgz", + "integrity": "sha512-8wggCTKGgzB1o8co3Wvj+p9pKN7T7q3C477lEz3NLjvPVzUti8rv9i45Di+4aO/k+HvzGh3s8QdNlXU2Bl4avQ==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2" + } + }, + "angular2-template-loader": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz", + "integrity": "sha1-wNROkP/w+sleiyPwQ6zaf9HFHXw=", + "dev": true, + "requires": { + "loader-utils": "^0.2.15" + }, + "dependencies": { + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + } + } + }, + "ansi": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", + "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=", + "dev": true + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "app-root-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.1.0.tgz", + "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=", + "dev": true + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-each": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.2.tgz", + "integrity": "sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==", + "dev": true + }, + "async-each-series": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz", + "integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "9.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.7.tgz", + "integrity": "sha512-qS5wW6aXHkm53Y4z73tFGsUhmZu4aMPV9iHXYlF0c/wxjknXNHuj/1cIQb+6YH692DbJGGWcckAXX+VxKvahMA==", + "dev": true, + "requires": { + "browserslist": "^4.4.1", + "caniuse-lite": "^1.0.30000932", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.14", + "postcss-value-parser": "^3.3.1" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "dev": true, + "requires": { + "follow-redirects": "^1.2.5", + "is-buffer": "^1.1.5" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "babel-extract-comments": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-extract-comments/-/babel-extract-comments-1.0.0.tgz", + "integrity": "sha512-qWWzi4TlddohA91bFwgt6zO/J0X+io7Qp184Fw0m2JYRSTZnJbFR8+07KmzudHCZgOiKRCrjhylwv9Xd8gfhVQ==", + "dev": true, + "requires": { + "babylon": "^6.18.0" + } + }, + "babel-jest": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.5.0.tgz", + "integrity": "sha512-0fKCXyRwxFTJL0UXDJiT2xYxO9Lu2vBd9n+cC+eDjESzcVG3s2DRGAxbzJX21fceB1WYoBjAh8pQ83dKcl003g==", + "dev": true, + "requires": { + "@jest/transform": "^24.5.0", + "@jest/types": "^24.5.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.3.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "babel-plugin-istanbul": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.1.tgz", + "integrity": "sha512-RNNVv2lsHAXJQsEJ5jonQwrJVWK8AcZpG1oxhnjCUaAjL7xahYLANhPUZbzEQHjKy1NMYUwn+0NPKQc8iSY4xQ==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.0.0", + "test-exclude": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + } + } + }, + "babel-plugin-jest-hoist": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.3.0.tgz", + "integrity": "sha512-nWh4N1mVH55Tzhx2isvUN5ebM5CDUvIpXPZYMRazQughie/EqGnbR+czzoQlhUmJG9pPJmYDRhvocotb2THl1w==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } + }, + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", + "requires": { + "babel-runtime": "^6.22.0", + "core-js": "^2.4.0", + "regenerator-runtime": "^0.10.0" + } + }, + "babel-preset-jest": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.3.0.tgz", + "integrity": "sha512-VGTV2QYBa/Kn3WCOKdfS31j9qomaXSgJqi65B6o05/1GsJyj9LVhSljM9ro4S+IBGj/ENhNBuH9bpqzztKAQSw==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.3.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base62": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/base62/-/base62-1.2.8.tgz", + "integrity": "sha512-V6YHUbjLxN1ymqNLb1DPHoU1CpfdL7d2YTIp5W3U4hhoG4hhxNmsFDs66M9EXxBiSEke5Bt5dwdfMwwZF70iLA==", + "dev": true + }, + "base64-arraybuffer": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", + "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", + "dev": true + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "base64id": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", + "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", + "dev": true, + "requires": { + "callsite": "1.0.0" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", + "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==", + "dev": true + }, + "binaryextensions": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.2.tgz", + "integrity": "sha512-xVNN69YGDghOqCCtA6FI7avYrr02mTJjOgB0/f1VPD3pJC8QEvjTKWc4epDx8AqxxA75NI0QpVM2gPJXUbE4Tg==", + "dev": true + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", + "dev": true + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "bootstrap": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.2.1.tgz", + "integrity": "sha512-tt/7vIv3Gm2mnd/WeDx36nfGGHleil0Wg8IeB7eMrVkY0fZ5iTaBisSh8oNANc2IBsCc6vCgCNTIM/IEN0+50Q==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browser-sync": { + "version": "2.26.3", + "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.26.3.tgz", + "integrity": "sha512-VLzpjCA4uXqfzkwqWtMM6hvPm2PNHp2RcmzBXcbi6C9WpkUhhFb8SVAr4CFrCsFxDg+oY6HalOjn8F+egyvhag==", + "dev": true, + "requires": { + "browser-sync-client": "^2.26.2", + "browser-sync-ui": "^2.26.2", + "bs-recipes": "1.3.4", + "bs-snippet-injector": "^2.0.1", + "chokidar": "^2.0.4", + "connect": "3.6.6", + "connect-history-api-fallback": "^1", + "dev-ip": "^1.0.1", + "easy-extender": "^2.3.4", + "eazy-logger": "^3", + "etag": "^1.8.1", + "fresh": "^0.5.2", + "fs-extra": "3.0.1", + "http-proxy": "1.15.2", + "immutable": "^3", + "localtunnel": "1.9.1", + "micromatch": "2.3.11", + "opn": "5.3.0", + "portscanner": "2.1.1", + "qs": "6.2.3", + "raw-body": "^2.3.2", + "resp-modifier": "6.0.2", + "rx": "4.1.0", + "send": "0.16.2", + "serve-index": "1.9.1", + "serve-static": "1.13.2", + "server-destroy": "1.0.1", + "socket.io": "2.1.1", + "ua-parser-js": "0.7.17", + "yargs": "6.4.0" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "opn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", + "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.4.0.tgz", + "integrity": "sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "window-size": "^0.2.0", + "y18n": "^3.2.1", + "yargs-parser": "^4.1.0" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + } + } + }, + "browser-sync-client": { + "version": "2.26.2", + "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.26.2.tgz", + "integrity": "sha512-FEuVJD41fI24HJ30XOT2RyF5WcnEtdJhhTqeyDlnMk/8Ox9MZw109rvk9pdfRWye4soZLe+xcAo9tHSMxvgAdw==", + "dev": true, + "requires": { + "etag": "1.8.1", + "fresh": "0.5.2", + "mitt": "^1.1.3", + "rxjs": "^5.5.6" + }, + "dependencies": { + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + } + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + } + } + }, + "browser-sync-ui": { + "version": "2.26.2", + "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.26.2.tgz", + "integrity": "sha512-LF7GMWo8ELOE0eAlxuRCfnGQT1ZxKP9flCfGgZdXFc6BwmoqaJHlYe7MmVvykKkXjolRXTz8ztXAKGVqNwJ3EQ==", + "dev": true, + "requires": { + "async-each-series": "0.1.1", + "connect-history-api-fallback": "^1", + "immutable": "^3", + "server-destroy": "1.0.1", + "socket.io-client": "^2.0.4", + "stream-throttle": "^0.1.3" + } + }, + "browser-sync-webpack-plugin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/browser-sync-webpack-plugin/-/browser-sync-webpack-plugin-2.2.2.tgz", + "integrity": "sha512-x92kl8LdBi4dp6YVXYqrSoDkOCOLCeBOrYSY0h9Sk1VcCDSoZC1Vc62eae6TfC2ljN4/L+aYlkzE46kirHzbgA==", + "dev": true, + "requires": { + "lodash": "^4" + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.1.tgz", + "integrity": "sha512-/pPw5IAUyqaQXGuD5vS8tcbudyPZ241jk1W5pQBsGDfcjNQt7p8qxZhgMNuygDShte1PibLFexecWUPgmVLfrg==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000949", + "electron-to-chromium": "^1.3.116", + "node-releases": "^1.1.11" + } + }, + "bs-recipes": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz", + "integrity": "sha1-DS1NSKcYyMBEdp/cT4lZLci2lYU=", + "dev": true + }, + "bs-snippet-injector": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz", + "integrity": "sha1-YbU5PxH1JVntEgaTEANDtu2wTdU=", + "dev": true + }, + "bser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", + "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cacache": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", + "dev": true, + "requires": { + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cache-loader": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-2.0.1.tgz", + "integrity": "sha512-V99T3FOynmGx26Zom+JrVBytLBsmUCzVG2/4NnUKgvXN4bEV42R1ERl1IyiH/cvFIDA1Ytq2lPZ9tXDSahcQpQ==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.0", + "normalize-path": "^3.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30000950", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000950.tgz", + "integrity": "sha512-Cs+4U9T0okW2ftBsCIHuEYXXkki7mjXmjCh4c6PzYShk04qDEr76/iC7KwhLoWoY65wcra1XOsRD+S7BptEb5A==", + "dev": true + }, + "canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "chevrotain": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-4.2.0.tgz", + "integrity": "sha512-uiwhNpkudwrk3rHxKKfrvsWNe4SBDjnswbF2FDqDfrqsfYr4gY0Yl1k2m9yPKR0fqfbiIP67EbgOv4e+JP+GGg==", + "dev": true, + "requires": { + "regexp-to-ast": "0.3.5" + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" + } + }, + "chownr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", + "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "dev": true, + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + } + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-deep": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", + "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.0", + "shallow-clone": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "closest-file-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/closest-file-data/-/closest-file-data-0.1.4.tgz", + "integrity": "sha1-l1+HwTLymdJKA3W59jyj+4j3Kzo=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "codelyzer": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-4.5.0.tgz", + "integrity": "sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==", + "dev": true, + "requires": { + "app-root-path": "^2.1.0", + "css-selector-tokenizer": "^0.7.0", + "cssauron": "^1.4.0", + "semver-dsl": "^1.0.1", + "source-map": "^0.5.7", + "sprintf-js": "^1.1.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=", + "dev": true + }, + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", + "dev": true + }, + "colorspace": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz", + "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==", + "dev": true, + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "common-tags": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", + "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "commoner": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", + "integrity": "sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=", + "dev": true, + "requires": { + "commander": "^2.5.0", + "detective": "^4.3.1", + "glob": "^5.0.15", + "graceful-fs": "^4.1.2", + "iconv-lite": "^0.4.5", + "mkdirp": "^0.5.0", + "private": "^0.1.6", + "q": "^1.1.2", + "recast": "^0.11.17" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "compare-versions": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.4.0.tgz", + "integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==", + "dev": true + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", + "dev": true + }, + "compressible": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.16.tgz", + "integrity": "sha512-JQfEOdnI7dASwCuSPWIeVYwc/zMsu/+tRhoUvEfXz2gxOA2DNjmG5vhtFdBlhWPPGo+RdT9S3tgc/uH5qgDiiA==", + "dev": true, + "requires": { + "mime-db": ">= 1.38.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "conf": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/conf/-/conf-2.0.0.tgz", + "integrity": "sha512-iCLzBsGFi8S73EANsEJZz0JnJ/e5VZef/kSaxydYZLAvw0rFNAUx5R7K5leC/CXXR2mZfXWhUvcZOO/dM2D5xg==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "env-paths": "^1.0.0", + "make-dir": "^1.0.0", + "pkg-up": "^2.0.0", + "write-file-atomic": "^2.3.0" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz", + "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==", + "dev": true, + "requires": { + "cacache": "^10.0.4", + "find-cache-dir": "^1.0.0", + "globby": "^7.1.1", + "is-glob": "^4.0.0", + "loader-utils": "^1.1.0", + "minimatch": "^3.0.4", + "p-limit": "^1.0.0", + "serialize-javascript": "^1.4.0" + }, + "dependencies": { + "cacache": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", + "dev": true, + "requires": { + "bluebird": "^3.5.1", + "chownr": "^1.0.1", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "lru-cache": "^4.1.1", + "mississippi": "^2.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^5.2.4", + "unique-filename": "^1.1.0", + "y18n": "^4.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mississippi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", + "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^2.0.1", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.1" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "core-js": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.4.tgz", + "integrity": "sha512-05qQ5hXShcqGkPZpXEFLIpxayZscVD2kuMBZewxiIPPEagukO4mqgPA9CWhUvFBJfy3ODdK2p9xyHh7FTU9/7A==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.1.0.tgz", + "integrity": "sha512-kCNPvthka8gvLtzAxQXvWo4FxqRB+ftRZyPZNuab5ngvM9Y7yw7hbEysglptLgpkGX9nAOKTBVkHUAe8xtYR6Q==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "lodash.get": "^4.4.2", + "parse-json": "^4.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, + "css-loader": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.0.tgz", + "integrity": "sha512-MoOu+CStsGrSt5K2OeZ89q3Snf+IkxRfAIt9aAKg4piioTrhtP1iEFPu+OVn3Ohz24FO6L+rw9UJxBILiSBw5Q==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "loader-utils": "^1.2.1", + "lodash": "^4.17.11", + "postcss": "^7.0.6", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.3", + "postcss-modules-scope": "^2.0.0", + "postcss-modules-values": "^2.0.0", + "postcss-value-parser": "^3.3.0", + "schema-utils": "^1.0.0" + } + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-selector-tokenizer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", + "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", + "dev": true, + "requires": { + "cssesc": "^0.1.0", + "fastparse": "^1.1.1", + "regexpu-core": "^1.0.0" + } + }, + "css-tree": { + "version": "1.0.0-alpha.28", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz", + "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==", + "dev": true, + "requires": { + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "css-unit-converter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", + "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", + "dev": true + }, + "css-url-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz", + "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=", + "dev": true + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "dev": true + }, + "cssauron": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", + "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=", + "dev": true, + "requires": { + "through": "X.X.X" + } + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true + }, + "csso": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", + "integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==", + "dev": true, + "requires": { + "css-tree": "1.0.0-alpha.29" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.29", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz", + "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==", + "dev": true, + "requires": { + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "cssom": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", + "dev": true + }, + "cssstyle": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.1.tgz", + "integrity": "sha512-7DYm8qe+gPx/h77QlCyFmX80+fGaE/6A/Ekl0zaszYOubvySO2saYFdQ78P29D0UsULxFKCetDGNaNRUdSF+2A==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, + "d3": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", + "integrity": "sha1-vEZ0gAQ3iyGjYMn8fPUjF5B2L7g=", + "dev": true + }, + "dargs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-6.0.0.tgz", + "integrity": "sha512-6lJauzNaI7MiM8EHQWmGj+s3rP5/i1nYs8GAvKrLAx/9dpc9xS/4seFb1ioR39A+kcfu4v3jnEa/EE5qWYnitQ==", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "default-gateway": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz", + "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==", + "dev": true, + "requires": { + "execa": "^0.10.0", + "ip-regex": "^2.1.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", + "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "dependency-graph": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz", + "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-conflict": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz", + "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", + "dev": true + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true, + "requires": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } + }, + "dev-ip": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", + "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=", + "dev": true + }, + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "dev": true, + "requires": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } + }, + "didyoumean": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.1.tgz", + "integrity": "sha1-6S7f2tplN9SE1zwBcv0eugxJdv8=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "diff-sequences": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.3.0.tgz", + "integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "drange": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", + "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==", + "dev": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "easy-extender": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", + "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "eazy-logger": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-3.0.2.tgz", + "integrity": "sha1-oyWqXlPROiIliJsqxBE7K5Y29Pw=", + "dev": true, + "requires": { + "tfunk": "^3.0.1" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "editions": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/editions/-/editions-2.1.3.tgz", + "integrity": "sha512-xDZyVm0A4nLgMNWVVLJvcwMjI80ShiH/27RyLiCnW1L273TcJIA25C4pwJ33AWV01OX6UriP35Xu+lH4S7HWQw==", + "dev": true, + "requires": { + "errlop": "^1.1.1", + "semver": "^5.6.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.116", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.116.tgz", + "integrity": "sha512-NKwKAXzur5vFCZYBHpdWjTMO8QptNLNP80nItkSIgUOapPAo9Uia+RvkCaZJtO7fhQaVElSvBPWEc2ku6cKsPA==", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "dev": true, + "requires": { + "env-variable": "0.0.x" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "engine.io-client": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz", + "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-parser": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", + "dev": true, + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "env-paths": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", + "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=", + "dev": true + }, + "env-variable": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", + "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==", + "dev": true + }, + "envify": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/envify/-/envify-3.4.1.tgz", + "integrity": "sha1-1xIjKejfFoi6dxsSUBkXyc5cvOg=", + "dev": true, + "requires": { + "jstransform": "^11.0.3", + "through": "~2.3.4" + } + }, + "err-code": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", + "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", + "dev": true + }, + "errlop": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/errlop/-/errlop-1.1.1.tgz", + "integrity": "sha512-WX7QjiPHhsny7/PQvrhS5VMizXXKoKCS3udaBp8gjlARdbn+XmK300eKBAAN0hGyRaTCtRpOaxK+xFVPUJ3zkw==", + "dev": true, + "requires": { + "editions": "^2.1.2" + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "dev": true, + "requires": { + "string-template": "~0.2.1", + "xtend": "~4.0.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "error-stack-parser": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.2.tgz", + "integrity": "sha512-E1fPutRDdIj/hohG0UpT5mayXNCxXP9d+snxFsPU9X0XgccOumKraa3juDMwTUyi7+Bu5+mCGagjg4IYeNbOdw==", + "dev": true, + "requires": { + "stackframe": "^1.0.4" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "es6-templates": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", + "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", + "dev": true, + "requires": { + "recast": "~0.11.12", + "through": "~2.3.6" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + }, + "events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", + "dev": true + }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exec-sh": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "expect": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.5.0.tgz", + "integrity": "sha512-p2Gmc0CLxOgkyA93ySWmHFYHUPFIHG6XZ06l7WArWAsrqYVaVEkOU5NtT5i68KUyGKbkQgDCkiT65bWmdoL6Bw==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.3.0", + "jest-matcher-utils": "^24.5.0", + "jest-message-util": "^24.5.0", + "jest-regex-util": "^24.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-glob": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.6.tgz", + "integrity": "sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", + "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==", + "dev": true + }, + "fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "^2.0.0" + } + }, + "fbjs": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.6.1.tgz", + "integrity": "sha1-lja3cF9bqWhNRLcveDISVK/IYPc=", + "dev": true, + "requires": { + "core-js": "^1.0.0", + "loose-envify": "^1.0.0", + "promise": "^7.0.3", + "ua-parser-js": "^0.7.9", + "whatwg-fetch": "^0.9.0" + }, + "dependencies": { + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + } + } + }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==", + "dev": true + }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", + "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } + }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^2.0.0" + } + }, + "find-parent-dir": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", + "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "fn-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", + "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=", + "dev": true + }, + "follow-redirects": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", + "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", + "dev": true, + "requires": { + "debug": "^3.2.6" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "fork-ts-checker-webpack-plugin": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-0.5.2.tgz", + "integrity": "sha512-a5IG+xXyKnpruI0CP/anyRLAoxWtp3lzdG6flxicANnoSzz64b12dJ7ASAVRrI2OaWwZR2JyBaMHFQqInhWhIw==", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "chalk": "^2.4.1", + "chokidar": "^2.0.4", + "micromatch": "^3.1.10", + "minimatch": "^3.0.4", + "tapable": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "friendly-errors-webpack-plugin": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.0.tgz", + "integrity": "sha512-K27M3VK30wVoOarP651zDmb93R9zF28usW4ocaK3mfQeIEI5BPht/EzZs5E8QLLwbLRJQMwscAjDxYPb1FuNiw==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "error-stack-parser": "^2.0.0", + "string-width": "^2.0.0" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^3.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "dev": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "g-status": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/g-status/-/g-status-2.0.2.tgz", + "integrity": "sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "matcher": "^1.0.0", + "simple-git": "^1.85.0" + } + }, + "gauge": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", + "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", + "dev": true, + "requires": { + "ansi": "^0.3.0", + "has-unicode": "^2.0.0", + "lodash.pad": "^4.1.0", + "lodash.padend": "^4.1.0", + "lodash.padstart": "^4.1.0" + } + }, + "generator-jhipster": { + "version": "5.8.2", + "resolved": "https://registry.npmjs.org/generator-jhipster/-/generator-jhipster-5.8.2.tgz", + "integrity": "sha512-GW33cKnIf0wWuK411U9GDiNKwKVLbL4BpAqyR4b9JD6ClhwHsQg3HRlItN8pV0iTHJtyFnSfcV/9nJIHFWwvKA==", + "dev": true, + "requires": { + "axios": "0.18.0", + "chalk": "2.4.1", + "commander": "2.16.0", + "conf": "2.0.0", + "didyoumean": "1.2.1", + "ejs": "2.6.1", + "glob": "7.1.2", + "gulp-filter": "5.1.0", + "insight": "0.10.1", + "jhipster-core": "3.6.11", + "js-object-pretty-print": "0.3.0", + "js-yaml": "3.12.0", + "lodash": "4.17.10", + "meow": "5.0.0", + "mkdirp": "0.5.1", + "os-locale": "2.1.0", + "parse-gitignore": "1.0.1", + "pluralize": "7.0.0", + "prettier": "1.13.7", + "randexp": "0.4.9", + "semver": "5.5.0", + "shelljs": "0.8.2", + "tabtab": "2.2.2", + "through2": "2.0.3", + "uuid": "3.3.2", + "yeoman-environment": "2.3.0", + "yeoman-generator": "3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "axios": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "dev": true, + "requires": { + "follow-redirects": "^1.3.0", + "is-buffer": "^1.1.5" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "commander": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", + "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "prettier": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.13.7.tgz", + "integrity": "sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "shelljs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", + "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + } + } + }, + "genfun": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", + "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", + "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", + "dev": true + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "gh-got": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz", + "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", + "dev": true, + "requires": { + "got": "^7.0.0", + "is-plain-obj": "^1.1.0" + } + }, + "github-username": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", + "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", + "dev": true, + "requires": { + "gh-got": "^6.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "dev": true, + "requires": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + }, + "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "grouped-queue": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", + "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", + "dev": true, + "requires": { + "lodash": "^4.17.2" + } + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "gulp-filter": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.1.0.tgz", + "integrity": "sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM=", + "dev": true, + "requires": { + "multimatch": "^2.0.0", + "plugin-error": "^0.1.2", + "streamfilter": "^1.0.5" + } + }, + "handle-thing": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", + "dev": true + }, + "handlebars": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", + "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "dev": true, + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "dev": true, + "requires": { + "has-symbol-support-x": "^1.4.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, + "html-loader": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz", + "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==", + "dev": true, + "requires": { + "es6-templates": "^0.2.3", + "fastparse": "^1.1.1", + "html-minifier": "^3.5.8", + "loader-utils": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + } + } + }, + "html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", + "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", + "dev": true, + "requires": { + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", + "util.promisify": "1.0.0" + }, + "dependencies": { + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + } + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "dependencies": { + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", + "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", + "dev": true + }, + "http-proxy": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.15.2.tgz", + "integrity": "sha1-ZC/cr/5S00SNK9o7AHnpQJBk2jE=", + "dev": true, + "requires": { + "eventemitter3": "1.x.x", + "requires-port": "1.x.x" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "http-proxy-middleware": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", + "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", + "dev": true, + "requires": { + "http-proxy": "^1.16.2", + "is-glob": "^4.0.0", + "lodash": "^4.17.5", + "micromatch": "^3.1.9" + }, + "dependencies": { + "eventemitter3": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "dev": true + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "dev": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "husky": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-1.3.1.tgz", + "integrity": "sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.7", + "execa": "^1.0.0", + "find-up": "^3.0.0", + "get-stdin": "^6.0.0", + "is-ci": "^2.0.0", + "pkg-dir": "^3.0.0", + "please-upgrade-node": "^3.1.1", + "read-pkg": "^4.0.1", + "run-node": "^1.0.0", + "slash": "^2.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "read-pkg": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", + "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "dev": true, + "requires": { + "normalize-package-data": "^2.3.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "icss-utils": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.0.tgz", + "integrity": "sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "ignore-walk": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "immutable": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", + "integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=", + "dev": true + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.0.6.tgz", + "integrity": "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=", + "requires": { + "ansi-escapes": "^1.1.0", + "chalk": "^1.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.1", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx": "^4.1.0", + "string-width": "^2.0.0", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "insight": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/insight/-/insight-0.10.1.tgz", + "integrity": "sha512-kLGeYQkh18f8KuC68QKdi0iwUcIaayJVB/STpX7x452/7pAUm1yfG4giJwcxbrTh0zNYtc8kBR+6maLMOzglOQ==", + "dev": true, + "requires": { + "async": "^2.1.4", + "chalk": "^2.3.0", + "conf": "^1.3.1", + "inquirer": "^5.0.0", + "lodash.debounce": "^4.0.8", + "os-name": "^2.0.1", + "request": "^2.74.0", + "tough-cookie": "^2.0.0", + "uuid": "^3.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "conf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/conf/-/conf-1.4.0.tgz", + "integrity": "sha512-bzlVWS2THbMetHqXKB8ypsXN4DQ/1qopGwNJi1eYbpwesJcd86FBjFciCQX/YwAhp9bM7NVnPFqZ5LpV7gP0Dg==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "env-paths": "^1.0.0", + "make-dir": "^1.0.0", + "pkg-up": "^2.0.0", + "write-file-atomic": "^2.3.0" + } + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.1.0", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^5.5.2", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + } + } + }, + "internal-ip": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-3.0.1.tgz", + "integrity": "sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==", + "dev": true, + "requires": { + "default-gateway": "^2.6.0", + "ipaddr.js": "^1.5.2" + } + }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", + "dev": true + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-generator-fn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.0.0.tgz", + "integrity": "sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g==", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-number-like": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", + "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "dev": true, + "requires": { + "lodash.isfinite": "^3.3.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=", + "dev": true + }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-scoped": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", + "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", + "dev": true, + "requires": { + "scoped-regex": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "dev": true, + "requires": { + "html-comment-regex": "^1.1.0" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "dev": true, + "requires": { + "punycode": "2.x.x" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-api": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.1.tgz", + "integrity": "sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==", + "dev": true, + "requires": { + "async": "^2.6.1", + "compare-versions": "^3.2.1", + "fileset": "^2.0.3", + "istanbul-lib-coverage": "^2.0.3", + "istanbul-lib-hook": "^2.0.3", + "istanbul-lib-instrument": "^3.1.0", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.2", + "istanbul-reports": "^2.1.1", + "js-yaml": "^3.12.0", + "make-dir": "^1.3.0", + "minimatch": "^3.0.4", + "once": "^1.4.0" + }, + "dependencies": { + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + } + } + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz", + "integrity": "sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA==", + "dev": true, + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz", + "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", + "dev": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "istanbul-lib-report": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz", + "integrity": "sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "supports-color": "^6.0.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz", + "integrity": "sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "rimraf": "^2.6.2", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.1.1.tgz", + "integrity": "sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw==", + "dev": true, + "requires": { + "handlebars": "^4.1.0" + } + }, + "istextorbinary": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.5.1.tgz", + "integrity": "sha512-pv/JNPWnfpwGjPx7JrtWTwsWsxkrK3fNzcEVnt92YKEIErps4Fsk49+qzCe9iQF2hjqK8Naqf8P9kzoeCuQI1g==", + "dev": true, + "requires": { + "binaryextensions": "^2.1.2", + "editions": "^2.1.3", + "textextensions": "^2.4.0" + } + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "dev": true, + "requires": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + } + }, + "jest": { + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.1.0.tgz", + "integrity": "sha512-+q91L65kypqklvlRFfXfdzUKyngQLOcwGhXQaLmVHv+d09LkNXuBuGxlofTFW42XMzu3giIcChchTsCNUjQ78A==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "jest-cli": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.5.0.tgz", + "integrity": "sha512-P+Jp0SLO4KWN0cGlNtC7JV0dW1eSFR7eRpoOucP2UM0sqlzp/bVHeo71Omonvigrj9AvCKy7NtQANtqJ7FXz8g==", + "dev": true, + "requires": { + "@jest/core": "^24.5.0", + "@jest/test-result": "^24.5.0", + "@jest/types": "^24.5.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.5.0", + "jest-util": "^24.5.0", + "jest-validate": "^24.5.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^12.0.2" + } + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz", + "integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz", + "integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "jest-changed-files": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.5.0.tgz", + "integrity": "sha512-Ikl29dosYnTsH9pYa1Tv9POkILBhN/TLZ37xbzgNsZ1D2+2n+8oEZS2yP1BrHn/T4Rs4Ggwwbp/x8CKOS5YJOg==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } + } + }, + "jest-config": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.5.0.tgz", + "integrity": "sha512-t2UTh0Z2uZhGBNVseF8wA2DS2SuBiLOL6qpLq18+OZGfFUxTM7BzUVKyHFN/vuN+s/aslY1COW95j1Rw81huOQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.5.0", + "babel-jest": "^24.5.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.5.0", + "jest-environment-node": "^24.5.0", + "jest-get-type": "^24.3.0", + "jest-jasmine2": "^24.5.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.5.0", + "jest-util": "^24.5.0", + "jest-validate": "^24.5.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.5.0", + "realpath-native": "^1.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-diff": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.5.0.tgz", + "integrity": "sha512-mCILZd9r7zqL9Uh6yNoXjwGQx0/J43OD2vvWVKwOEOLZliQOsojXwqboubAQ+Tszrb6DHGmNU7m4whGeB9YOqw==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-docblock": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.3.0.tgz", + "integrity": "sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.5.0.tgz", + "integrity": "sha512-6gy3Kh37PwIT5sNvNY2VchtIFOOBh8UCYnBlxXMb5sr5wpJUDPTUATX2Axq1Vfk+HWTMpsYPeVYp4TXx5uqUBw==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.3.0", + "jest-util": "^24.5.0", + "pretty-format": "^24.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-environment-jsdom": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.5.0.tgz", + "integrity": "sha512-62Ih5HbdAWcsqBx2ktUnor/mABBo1U111AvZWcLKeWN/n/gc5ZvDBKe4Og44fQdHKiXClrNGC6G0mBo6wrPeGQ==", + "dev": true, + "requires": { + "@jest/environment": "^24.5.0", + "@jest/fake-timers": "^24.5.0", + "@jest/types": "^24.5.0", + "jest-mock": "^24.5.0", + "jest-util": "^24.5.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.5.0.tgz", + "integrity": "sha512-du6FuyWr/GbKLsmAbzNF9mpr2Iu2zWSaq/BNHzX+vgOcts9f2ayXBweS7RAhr+6bLp6qRpMB6utAMF5Ygktxnw==", + "dev": true, + "requires": { + "@jest/environment": "^24.5.0", + "@jest/fake-timers": "^24.5.0", + "@jest/types": "^24.5.0", + "jest-mock": "^24.5.0", + "jest-util": "^24.5.0" + } + }, + "jest-get-type": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.3.0.tgz", + "integrity": "sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow==", + "dev": true + }, + "jest-haste-map": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.5.0.tgz", + "integrity": "sha512-mb4Yrcjw9vBgSvobDwH8QUovxApdimGcOkp+V1ucGGw4Uvr3VzZQBJhNm1UY3dXYm4XXyTW2G7IBEZ9pM2ggRQ==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.4.0", + "jest-util": "^24.5.0", + "jest-worker": "^24.4.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3" + } + }, + "jest-jasmine2": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.5.0.tgz", + "integrity": "sha512-sfVrxVcx1rNUbBeyIyhkqZ4q+seNKyAG6iM0S2TYBdQsXjoFDdqWFfsUxb6uXSsbimbXX/NMkJIwUZ1uT9+/Aw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.5.0", + "@jest/test-result": "^24.5.0", + "@jest/types": "^24.5.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.5.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.5.0", + "jest-matcher-utils": "^24.5.0", + "jest-message-util": "^24.5.0", + "jest-runtime": "^24.5.0", + "jest-snapshot": "^24.5.0", + "jest-util": "^24.5.0", + "pretty-format": "^24.5.0", + "throat": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-junit": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-6.2.1.tgz", + "integrity": "sha512-zMbwKzZGo9TQOjdBUNQdTEf81QvOrwiQtLIUSEyCwPXYx/G/DJGXEJcqs8viXxn6poJ4Xh4pYGDLD0DKDwtfVA==", + "dev": true, + "requires": { + "jest-validate": "^24.0.0", + "mkdirp": "^0.5.1", + "strip-ansi": "^4.0.0", + "xml": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "jest-leak-detector": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.5.0.tgz", + "integrity": "sha512-LZKBjGovFRx3cRBkqmIg+BZnxbrLqhQl09IziMk3oeh1OV81Hg30RUIx885mq8qBv1PA0comB9bjKcuyNO1bCQ==", + "dev": true, + "requires": { + "pretty-format": "^24.5.0" + } + }, + "jest-matcher-utils": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.5.0.tgz", + "integrity": "sha512-QM1nmLROjLj8GMGzg5VBra3I9hLpjMPtF1YqzQS3rvWn2ltGZLrGAO1KQ9zUCVi5aCvrkbS5Ndm2evIP9yZg1Q==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.5.0", + "jest-get-type": "^24.3.0", + "pretty-format": "^24.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-message-util": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.5.0.tgz", + "integrity": "sha512-6ZYgdOojowCGiV0D8WdgctZEAe+EcFU+KrVds+0ZjvpZurUW2/oKJGltJ6FWY2joZwYXN5VL36GPV6pNVRqRnQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.5.0", + "@jest/types": "^24.5.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-mock": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.5.0.tgz", + "integrity": "sha512-ZnAtkWrKf48eERgAOiUxVoFavVBziO2pAi2MfZ1+bGXVkDfxWLxU0//oJBkgwbsv6OAmuLBz4XFFqvCFMqnGUw==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "dev": true + }, + "jest-preset-angular": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-6.0.2.tgz", + "integrity": "sha512-uhrllY41tUvkeR41aX9bU5w3/EvvmwZiJ3UitDhRSEJL2Jvq2N/xKlmw7qvlZoGZnciFjOUJ2WDKv5fmCrvnQA==", + "dev": true, + "requires": { + "@types/jest": "^23.3.1", + "jest-zone-patch": ">=0.0.9 <1.0.0", + "ts-jest": "~23.1.3" + }, + "dependencies": { + "@types/jest": { + "version": "23.3.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.14.tgz", + "integrity": "sha512-Q5hTcfdudEL2yOmluA1zaSyPbzWPmJ3XfSWeP3RyoYvS9hnje1ZyagrZOuQ6+1nQC1Gw+7gap3pLNL3xL6UBug==", + "dev": true + } + } + }, + "jest-regex-util": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.3.0.tgz", + "integrity": "sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==", + "dev": true + }, + "jest-resolve": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.5.0.tgz", + "integrity": "sha512-ZIfGqLX1Rg8xJpQqNjdoO8MuxHV1q/i2OO1hLXjgCWFWs5bsedS8UrOdgjUqqNae6DXA+pCyRmdcB7lQEEbXew==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.5.0.tgz", + "integrity": "sha512-dRVM1D+gWrFfrq2vlL5P9P/i8kB4BOYqYf3S7xczZ+A6PC3SgXYSErX/ScW/469pWMboM1uAhgLF+39nXlirCQ==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.5.0" + } + }, + "jest-runner": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.5.0.tgz", + "integrity": "sha512-oqsiS9TkIZV5dVkD+GmbNfWBRPIvxqmlTQ+AQUJUQ07n+4xTSDc40r+aKBynHw9/tLzafC00DIbJjB2cOZdvMA==", + "dev": true, + "requires": { + "@jest/console": "^24.3.0", + "@jest/environment": "^24.5.0", + "@jest/test-result": "^24.5.0", + "@jest/types": "^24.5.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.5.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.5.0", + "jest-jasmine2": "^24.5.0", + "jest-leak-detector": "^24.5.0", + "jest-message-util": "^24.5.0", + "jest-resolve": "^24.5.0", + "jest-runtime": "^24.5.0", + "jest-util": "^24.5.0", + "jest-worker": "^24.4.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-runtime": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.5.0.tgz", + "integrity": "sha512-GTFHzfLdwpaeoDPilNpBrorlPoNZuZrwKKzKJs09vWwHo+9TOsIIuszK8cWOuKC7ss07aN1922Ge8fsGdsqCuw==", + "dev": true, + "requires": { + "@jest/console": "^24.3.0", + "@jest/environment": "^24.5.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.5.0", + "@jest/types": "^24.5.0", + "@types/yargs": "^12.0.2", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.5.0", + "jest-haste-map": "^24.5.0", + "jest-message-util": "^24.5.0", + "jest-mock": "^24.5.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.5.0", + "jest-snapshot": "^24.5.0", + "jest-util": "^24.5.0", + "jest-validate": "^24.5.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^12.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz", + "integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz", + "integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "jest-serializer": { + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.4.0.tgz", + "integrity": "sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q==", + "dev": true + }, + "jest-snapshot": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.5.0.tgz", + "integrity": "sha512-eBEeJb5ROk0NcpodmSKnCVgMOo+Qsu5z9EDl3tGffwPzK1yV37mjGWF2YeIz1NkntgTzP+fUL4s09a0+0dpVWA==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.5.0", + "chalk": "^2.0.1", + "expect": "^24.5.0", + "jest-diff": "^24.5.0", + "jest-matcher-utils": "^24.5.0", + "jest-message-util": "^24.5.0", + "jest-resolve": "^24.5.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.5.0", + "semver": "^5.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-sonar-reporter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-sonar-reporter/-/jest-sonar-reporter-2.0.0.tgz", + "integrity": "sha512-ZervDCgEX5gdUbdtWsjdipLN3bKJwpxbvhkYNXTAYvAckCihobSLr9OT/IuyNIRT1EZMDDwR6DroWtrq+IL64w==", + "dev": true, + "requires": { + "xml": "^1.0.1" + } + }, + "jest-util": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.5.0.tgz", + "integrity": "sha512-Xy8JsD0jvBz85K7VsTIQDuY44s+hYJyppAhcsHsOsGisVtdhar6fajf2UOf2mEVEgh15ZSdA0zkCuheN8cbr1Q==", + "dev": true, + "requires": { + "@jest/console": "^24.3.0", + "@jest/fake-timers": "^24.5.0", + "@jest/source-map": "^24.3.0", + "@jest/test-result": "^24.5.0", + "@jest/types": "^24.5.0", + "@types/node": "*", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "callsites": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", + "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-validate": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.5.0.tgz", + "integrity": "sha512-gg0dYszxjgK2o11unSIJhkOFZqNRQbWOAB2/LOUdsd2LfD9oXiMeuee8XsT0iRy5EvSccBgB4h/9HRbIo3MHgQ==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0", + "camelcase": "^5.0.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.3.0", + "leven": "^2.1.0", + "pretty-format": "^24.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-watcher": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.5.0.tgz", + "integrity": "sha512-/hCpgR6bg0nKvD3nv4KasdTxuhwfViVMHUATJlnGCD0r1QrmIssimPbmc5KfAQblAVxkD8xrzuij9vfPUk1/rA==", + "dev": true, + "requires": { + "@jest/test-result": "^24.5.0", + "@jest/types": "^24.5.0", + "@types/node": "*", + "@types/yargs": "^12.0.9", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.5.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-worker": { + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.4.0.tgz", + "integrity": "sha512-BH9X/klG9vxwoO99ZBUbZFfV8qO0XNZ5SIiCyYK2zOuJBl6YJVAeNIQjcoOVNu4HGEHeYEKsUWws8kSlSbZ9YQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^1.0.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-zone-patch": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/jest-zone-patch/-/jest-zone-patch-0.0.10.tgz", + "integrity": "sha512-K5uHLHgMgi2Eyj74gbY+xSeGGekb5U48bXsgDwgipRbFdaekyZK+TAcp8auamqU4UjrAt5S4sIUZz/2bBNyTTA==", + "dev": true + }, + "jhipster-core": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/jhipster-core/-/jhipster-core-3.6.11.tgz", + "integrity": "sha512-OibJay1+nwKk+mfRfuTrt2rW2h7BmGNfKWR7TQO4oYqG+I096EvJxZkIMCcjA9KuKLOZvnzfEi4UbtKyRTmHkg==", + "dev": true, + "requires": { + "chevrotain": "4.2.0", + "fs-extra": "7.0.1", + "lodash": "4.17.11", + "winston": "3.2.1" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + } + } + }, + "joi": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-11.4.0.tgz", + "integrity": "sha512-O7Uw+w/zEWgbL6OcHbyACKSj0PkQeUgmehdoXVSxt92QFCq4+1390Rwh5moI2K/OgC7D8RHRZqHZxT2husMJHA==", + "dev": true, + "requires": { + "hoek": "4.x.x", + "isemail": "3.x.x", + "topo": "2.x.x" + } + }, + "js-object-pretty-print": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/js-object-pretty-print/-/js-object-pretty-print-0.3.0.tgz", + "integrity": "sha1-RnDkUAZu4ezPNRdMfRl/WqOLz3Q=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jstransform": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-11.0.3.tgz", + "integrity": "sha1-CaeJk+CuTU70SH9hVakfYZDLQiM=", + "dev": true, + "requires": { + "base62": "^1.1.0", + "commoner": "^0.10.1", + "esprima-fb": "^15001.1.0-dev-harmony-fb", + "object-assign": "^2.0.0", + "source-map": "^0.4.2" + }, + "dependencies": { + "esprima-fb": { + "version": "15001.1.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1.0-dev-harmony-fb.tgz", + "integrity": "sha1-MKlHMDxrjV6VW+4rmbHSMyBqaQE=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "kleur": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.2.tgz", + "integrity": "sha512-3h7B2WRT5LNXOtQiAaWonilegHcPSf9nLVXlSTci8lu1dZUuui61+EsPEZqSVxY7rXYmB2DVKMQILxaO5WL61Q==", + "dev": true + }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "dev": true, + "requires": { + "colornames": "^1.1.1" + } + }, + "last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "dev": true, + "requires": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "limiter": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.4.tgz", + "integrity": "sha512-XCpr5bElgDI65vVgstP8TWjv6/QKWm9GU5UG0Pr5sLQ3QLo8NVKsioe+Jed5/3vFOe3IQuqE7DKwTvKQkjTHvg==", + "dev": true + }, + "lint-staged": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.3.tgz", + "integrity": "sha512-6TGkikL1B+6mIOuSNq2TV6oP21IhPMnV8q0cf9oYZ296ArTVNcbFh1l1pfVOHHbBIYLlziWNsQ2q45/ffmJ4AA==", + "dev": true, + "requires": { + "@iamstarkov/listr-update-renderer": "0.4.1", + "chalk": "^2.3.1", + "commander": "^2.14.1", + "cosmiconfig": "^5.0.2", + "debug": "^3.1.0", + "dedent": "^0.7.0", + "del": "^3.0.0", + "execa": "^1.0.0", + "find-parent-dir": "^0.3.0", + "g-status": "^2.0.2", + "is-glob": "^4.0.0", + "is-windows": "^1.0.2", + "listr": "^0.14.2", + "lodash": "^4.17.5", + "log-symbols": "^2.2.0", + "micromatch": "^3.1.8", + "npm-which": "^3.0.1", + "p-map": "^1.1.1", + "path-is-inside": "^1.0.2", + "pify": "^3.0.0", + "please-upgrade-node": "^3.0.2", + "staged-git-files": "1.1.2", + "string-argv": "^0.0.2", + "stringify-object": "^3.2.2", + "yup": "^0.26.10" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "p-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.0.0.tgz", + "integrity": "sha512-GO107XdrSUmtHxVoi60qc9tUl/KkNKm+X2CF4P9amalpGxv5YqVPJNfSb0wcA+syCopkZvYYIzW8OVTQW59x/w==", + "dev": true + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "localtunnel": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.1.tgz", + "integrity": "sha512-HWrhOslklDvxgOGFLxi6fQVnvpl6XdX4sPscfqMZkzi3gtt9V7LKBWYvNUcpHSVvjwCQ6xzXacVvICNbNcyPnQ==", + "dev": true, + "requires": { + "axios": "0.17.1", + "debug": "2.6.9", + "openurl": "1.1.1", + "yargs": "6.6.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^4.2.0" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lodash.isfinite": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", + "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.pad": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", + "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "lodash.padstart": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", + "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lodash.tail": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", + "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", + "dev": true + }, + "lodash.template": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", + "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", + "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", + "dev": true, + "requires": { + "lodash._reinterpolate": "~3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, + "logform": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", + "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", + "dev": true, + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "loglevel": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "macos-release": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-1.1.0.tgz", + "integrity": "sha512-mmLbumEYMi5nXReB9js3WGsB8UE6cDBWyIO62Z4DNx6GbRhDxHNjA1MlzSpJ2S2KM1wyiPRA0d19uHWYYvMHjA==", + "dev": true + }, + "magic-string": { + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz", + "integrity": "sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "make-fetch-happen": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz", + "integrity": "sha512-7R5ivfy9ilRJ1EMKIOziwrns9fGeAD4bAha8EB7BIiBBLHm2KeTUGCrICFt2rbHfzheTLynv50GnNTK1zDTrcQ==", + "dev": true, + "requires": { + "agentkeepalive": "^3.4.1", + "cacache": "^11.0.1", + "http-cache-semantics": "^3.8.1", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "mississippi": "^3.0.0", + "node-fetch-npm": "^2.0.2", + "promise-retry": "^1.1.1", + "socks-proxy-agent": "^4.0.0", + "ssri": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "matcher": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", + "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.4" + } + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", + "integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mem-fs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", + "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", + "dev": true, + "requires": { + "through2": "^2.0.0", + "vinyl": "^1.1.0", + "vinyl-file": "^2.0.0" + } + }, + "mem-fs-editor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-5.1.0.tgz", + "integrity": "sha512-2Yt2GCYEbcotYbIJagmow4gEtHDqzpq5XN94+yAx/NT5+bGqIjkXnm3KCUQfE6kRfScGp9IZknScoGRKu8L78w==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "deep-extend": "^0.6.0", + "ejs": "^2.5.9", + "glob": "^7.0.3", + "globby": "^8.0.1", + "isbinaryfile": "^3.0.2", + "mkdirp": "^0.5.0", + "multimatch": "^2.0.0", + "rimraf": "^2.2.8", + "through2": "^2.0.0", + "vinyl": "^2.0.1" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "path-type": "^3.0.0" + } + }, + "globby": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", + "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "2.0.0", + "fast-glob": "^2.0.2", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "meow": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "merge2": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", + "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", + "dev": true + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "dev": true, + "requires": { + "mime-db": "~1.38.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz", + "integrity": "sha512-IuaLjruM0vMKhUUT51fQdQzBYTX49dLj8w68ALEAe2A4iYNpIC4eMac67mt3NzycvjOlf07/kYxJDc0RTl1Wqw==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, + "minipass": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "dev": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mitt": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.1.3.tgz", + "integrity": "sha512-mUDCnVNsAi+eD6qA0HkRkwYczbLHJ49z17BGe2PYRhZL4wpZUFZGJHU7/5tmvohoma+Hdn0Vh/oJTiPEmgSruA==", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "dev": true, + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "moment-locales-webpack-plugin": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/moment-locales-webpack-plugin/-/moment-locales-webpack-plugin-1.0.7.tgz", + "integrity": "sha512-KjYpaAhmuzGFZl6534FlZoK7QtW3vqlxd+A17W9DlgHJ5yhXANy7AZJl7iYtZpWjAfMTAWiVrQ7YDZdkFO6uRw==", + "dev": true, + "requires": { + "lodash.difference": "^4.5.0" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "nan": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz", + "integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, + "ng-jhipster": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/ng-jhipster/-/ng-jhipster-0.9.1.tgz", + "integrity": "sha512-/ViJ6bNtc/4w6valKNvHKyvXF1cn1OBnSEh3Q8aEUHtmoyr9owReTGHT7ylNclthUsxztRMUS4GrMMEQ5kM09Q==", + "requires": { + "tslib": "^1.9.0" + } + }, + "ngx-cookie": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ngx-cookie/-/ngx-cookie-2.0.1.tgz", + "integrity": "sha512-3+agXZkoPxRP3IyELf7Eiuhk6TX+EAX974kkCR6Xjm+N7boEA+Fin2Q90AAE4XZzY48skkVzLH96TOikb5yU3g==" + }, + "ngx-infinite-scroll": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-7.0.1.tgz", + "integrity": "sha512-be9DAAuabV7VGI06/JUnS6pXC6mcBOzA4+SBCwOcP9WwJ2r5GjdZyOa34ls9hi1MnCOj3zrXLvPKQ/UDp6csIw==", + "requires": { + "opencollective": "^1.0.3" + } + }, + "ngx-webstorage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ngx-webstorage/-/ngx-webstorage-2.0.1.tgz", + "integrity": "sha512-AhBkl1v5sBLYiGC1DuHxM90B8OewqyhYhm+KGtJIFxMh5dj3tlNgPokmWCtKcUZF26m8MgxDDuP5e6NeDCpYQw==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-fetch": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", + "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "node-fetch-npm": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz", + "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "json-parse-better-errors": "^1.0.0", + "safe-buffer": "^5.1.1" + } + }, + "node-forge": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", + "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", + "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.0", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "0.0.4" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-notifier": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz", + "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, + "node-releases": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.11.tgz", + "integrity": "sha512-8v1j5KfP+s5WOTa1spNUAOfreajQPN12JXbRR0oDE+YrJBQCXBnNqUDj27EKpPLOoSiU3tKi3xGPB+JaOdUEQQ==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "npm-bundled": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz", + "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.6.0", + "osenv": "^0.1.5", + "semver": "^5.5.0", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-packlist": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.1.tgz", + "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", + "dev": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npm-path": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "dev": true, + "requires": { + "which": "^1.2.10" + } + }, + "npm-pick-manifest": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz", + "integrity": "sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "npm-package-arg": "^6.0.0", + "semver": "^5.4.1" + } + }, + "npm-registry-fetch": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-3.9.0.tgz", + "integrity": "sha512-srwmt8YhNajAoSAaDWndmZgx89lJwIZ1GWxOuckH4Coek4uHv5S+o/l9FLQe/awA+JwTnj4FJHldxhlXdZEBmw==", + "dev": true, + "requires": { + "JSONStream": "^1.3.4", + "bluebird": "^3.5.1", + "figgy-pudding": "^3.4.1", + "lru-cache": "^4.1.3", + "make-fetch-happen": "^4.0.1", + "npm-package-arg": "^6.1.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", + "dev": true, + "requires": { + "commander": "^2.9.0", + "npm-path": "^2.0.2", + "which": "^1.2.10" + } + }, + "npmlog": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", + "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", + "dev": true, + "requires": { + "ansi": "~0.3.1", + "are-we-there-yet": "~1.1.2", + "gauge": "~1.2.5" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nwsapi": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.1.tgz", + "integrity": "sha512-T5GaA1J/d34AC8mkrFD2O0DR17kwJ702ZOtJOsS8RpbsQZVOC2/xYFb1i/cw+xdM54JIlMuojjDOYct8GIWtwg==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-component": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", + "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", + "dev": true + }, + "object-path": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.9.2.tgz", + "integrity": "sha1-D9mnT8X60a45aLWGvaXGMr1sBaU=", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opencollective": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz", + "integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=", + "requires": { + "babel-polyfill": "6.23.0", + "chalk": "1.1.3", + "inquirer": "3.0.6", + "minimist": "1.2.0", + "node-fetch": "1.6.3", + "opn": "4.0.2" + } + }, + "openurl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", + "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", + "dev": true + }, + "opn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", + "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + } + } + }, + "optimize-css-assets-webpack-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.1.tgz", + "integrity": "sha512-Rqm6sSjWtx9FchdP0uzTQDc7GXDKnwVEGoSxjezPkzMewx7gEWE9IMUYKmigTRC4U3RaNSwYVnUDLuIdtTpm0A==", + "dev": true, + "requires": { + "cssnano": "^4.1.0", + "last-call-webpack-plugin": "^3.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-2.0.1.tgz", + "integrity": "sha1-uaOGNhwXrjohc27wWZQFyajF3F4=", + "dev": true, + "requires": { + "macos-release": "^1.0.0", + "win-release": "^1.0.0" + } + }, + "os-shim": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", + "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "dev": true + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pacote": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.4.0.tgz", + "integrity": "sha512-WQ1KL/phGMkedYEQx9ODsjj7xvwLSpdFJJdEXrLyw5SILMxcTNt5DTxT2Z93fXuLFYJBlZJdnwdalrQdB/rX5w==", + "dev": true, + "requires": { + "bluebird": "^3.5.3", + "cacache": "^11.3.2", + "figgy-pudding": "^3.5.1", + "get-stream": "^4.1.0", + "glob": "^7.1.3", + "lru-cache": "^5.1.1", + "make-fetch-happen": "^4.0.1", + "minimatch": "^3.0.4", + "minipass": "^2.3.5", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "normalize-package-data": "^2.4.0", + "npm-package-arg": "^6.1.0", + "npm-packlist": "^1.1.12", + "npm-pick-manifest": "^2.2.3", + "npm-registry-fetch": "^3.8.0", + "osenv": "^0.1.5", + "promise-inflight": "^1.0.1", + "promise-retry": "^1.1.1", + "protoduck": "^5.0.1", + "rimraf": "^2.6.2", + "safe-buffer": "^5.1.2", + "semver": "^5.6.0", + "ssri": "^6.0.1", + "tar": "^4.4.8", + "unique-filename": "^1.1.1", + "which": "^1.3.1" + } + }, + "pako": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", + "dev": true + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "~0.2.2", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, + "parse-asn1": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-gitignore": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-gitignore/-/parse-gitignore-1.0.1.tgz", + "integrity": "sha512-UGyowyjtx26n65kdAMWhm6/3uy5uSrpcuH7tt+QEVudiBoVS+eqHxD5kbi9oWVRwj7sCzXqwuM+rUGw7earl6A==", + "dev": true + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "parseqs": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", + "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseuri": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", + "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", + "dev": true, + "requires": { + "better-assert": "~1.0.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "please-upgrade-node": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz", + "integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + } + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "portfinder": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", + "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==", + "dev": true, + "requires": { + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" + } + }, + "portscanner": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz", + "integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=", + "dev": true, + "requires": { + "async": "1.5.2", + "is-number-like": "^1.0.3" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-calc": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz", + "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==", + "dev": true, + "requires": { + "css-unit-converter": "^1.1.1", + "postcss": "^7.0.5", + "postcss-selector-parser": "^5.0.0-rc.4", + "postcss-value-parser": "^3.3.1" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-load-config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", + "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", + "dev": true, + "requires": { + "cosmiconfig": "^4.0.0", + "import-cwd": "^2.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", + "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", + "dev": true, + "requires": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0", + "require-from-string": "^2.0.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", + "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0", + "postcss-value-parser": "^3.3.1" + } + }, + "postcss-modules-scope": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz", + "integrity": "sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", + "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "dev": true, + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^7.0.6" + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + } + }, + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "dependencies": { + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + } + } + }, + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", + "dev": true, + "requires": { + "is-svg": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "prettier": { + "version": "1.16.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", + "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", + "dev": true + }, + "pretty-bytes": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.1.0.tgz", + "integrity": "sha512-wa5+qGVg9Yt7PB6rYm3kXlKzgzgivYTLRandezh43jjRqgyDyP+9YxfJpJiLs9yKD1WeU8/OvtToWpW7255FtA==", + "dev": true + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, + "requires": { + "renderkid": "^2.0.1", + "utila": "~0.4" + } + }, + "pretty-format": { + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.5.0.tgz", + "integrity": "sha512-/3RuSghukCf8Riu5Ncve0iI+BzVkbRU5EeUoArKARZobREycuH5O4waxvaNIloEXdb0qwgmEAed5vTpX1HNROQ==", + "dev": true, + "requires": { + "@jest/types": "^24.5.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "requires": { + "asap": "~2.0.3" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-retry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", + "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "dev": true, + "requires": { + "err-code": "^1.0.0", + "retry": "^0.10.0" + } + }, + "prompts": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.0.4.tgz", + "integrity": "sha512-HTzM3UWp/99A0gk51gAegwo1QRYA7xjcZufMNe33rCclFszUYAuHe1fIN/3ZmiHeGPkUsNaRyQm1hHOfM0PKxA==", + "dev": true, + "requires": { + "kleur": "^3.0.2", + "sisteransi": "^1.0.0" + } + }, + "property-expr": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-1.5.1.tgz", + "integrity": "sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==", + "dev": true + }, + "protoduck": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", + "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "dev": true, + "requires": { + "genfun": "^5.0.0" + } + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "dev": true, + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.3.tgz", + "integrity": "sha1-HPyyXBCpsrSDBT/zn138kjOQjP4=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", + "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", + "dev": true + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true + }, + "randexp": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.9.tgz", + "integrity": "sha512-maAX1cnBkzIZ89O4tSQUOF098xjGMC8N+9vuY/WfHwg87THw6odD2Br35donlj5e6KnB1SB0QBHhTQhhDHuTPQ==", + "dev": true, + "requires": { + "drange": "^1.0.0", + "ret": "^0.2.0" + }, + "dependencies": { + "ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "dev": true + } + } + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "react": { + "version": "0.14.9", + "resolved": "https://registry.npmjs.org/react/-/react-0.14.9.tgz", + "integrity": "sha1-kRCmSXxJ1EuhwO3TF67CnC4NkdE=", + "dev": true, + "requires": { + "envify": "^3.0.0", + "fbjs": "^0.6.1" + } + }, + "react-dom": { + "version": "0.14.9", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-0.14.9.tgz", + "integrity": "sha1-BQZKPc8PsYgKOyv8nVjFXY2fYpM=", + "dev": true + }, + "react-is": { + "version": "16.8.4", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.4.tgz", + "integrity": "sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==", + "dev": true + }, + "read-chunk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", + "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", + "dev": true, + "requires": { + "pify": "^3.0.0", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "dev": true, + "requires": { + "ast-types": "0.9.6", + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp-to-ast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.3.5.tgz", + "integrity": "sha512-1CJygtdvsfNFwiyjaMLBWtg2tfEqx/jSZ8S6TV+GlNL8kiH8rb4cm5Pb7A/C2BpyM/fA8ZJEudlCwi/jvAY+Ow==", + "dev": true + }, + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "renderkid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.3.tgz", + "integrity": "sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA==", + "dev": true, + "requires": { + "css-select": "^1.1.0", + "dom-converter": "^0.2", + "htmlparser2": "^3.3.0", + "strip-ansi": "^3.0.0", + "utila": "^0.4.0" + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "dev": true, + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "resp-modifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz", + "integrity": "sha1-sSTeXE+6/LpUH0j/pzlw9KpFa08=", + "dev": true, + "requires": { + "debug": "^2.2.0", + "minimatch": "^3.0.2" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rsvp": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.4.tgz", + "integrity": "sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==", + "dev": true + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", + "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", + "dev": true + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" + }, + "rxjs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } + } + }, + "sass": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.17.0.tgz", + "integrity": "sha512-aFi9RQqrCYkHB2DaLKBBbdUhos1N5o3l1ke9N5JqWzgSPmYwZsdmA+ViPVatUy/RPA21uejgYVUXM7GCh8lcdw==", + "dev": true, + "requires": { + "chokidar": "^2.0.0" + } + }, + "sass-loader": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", + "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", + "dev": true, + "requires": { + "clone-deep": "^2.0.1", + "loader-utils": "^1.0.1", + "lodash.tail": "^4.1.1", + "neo-async": "^2.5.0", + "pify": "^3.0.0", + "semver": "^5.5.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "scoped-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", + "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=", + "dev": true + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.4.tgz", + "integrity": "sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw==", + "dev": true, + "requires": { + "node-forge": "0.7.5" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "semver-dsl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz", + "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "semver-intersect": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", + "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", + "dev": true, + "requires": { + "semver": "^5.0.0" + } + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", + "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==", + "dev": true + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", + "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "dev": true, + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^5.0.0", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-git": { + "version": "1.107.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.107.0.tgz", + "integrity": "sha512-t4OK1JRlp4ayKRfcW6owrWcRVLyHRUlhGd0uN6ZZTqfDq8a5XpcUdOKiGRNobHEuMtNqzp0vcJNvhYWwh5PsQA==", + "dev": true, + "requires": { + "debug": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "simple-progress-webpack-plugin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/simple-progress-webpack-plugin/-/simple-progress-webpack-plugin-1.1.2.tgz", + "integrity": "sha512-bNQfb3qSqbtsfxg6d0dGechUUJH2lZqKG5+bj2aoJmEA0rSzcm+2JVfC2YgkDABfuGItZ/O5ttt6BssWZW4SNg==", + "dev": true, + "requires": { + "chalk": "2.3.x", + "figures": "2.0.x", + "log-update": "2.3.x" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, + "sisteransi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.0.tgz", + "integrity": "sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ==", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "smart-buffer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", + "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + } + }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", + "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", + "dev": true + }, + "socket.io-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", + "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.3.1", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", + "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", + "dev": true + } + } + }, + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "dev": true, + "requires": { + "faye-websocket": "^0.10.0", + "uuid": "^3.0.1" + } + }, + "sockjs-client": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", + "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", + "dev": true, + "requires": { + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "socks": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz", + "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "4.0.2" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "dev": true, + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", + "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz", + "integrity": "sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==", + "dev": true + }, + "spawn-sync": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", + "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=", + "dev": true, + "requires": { + "concat-stream": "^1.4.7", + "os-shim": "^0.1.2" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", + "dev": true + }, + "spdy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", + "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "readable-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", + "dev": true + }, + "stackframe": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", + "integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==", + "dev": true + }, + "staged-git-files": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.2.tgz", + "integrity": "sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "stream-throttle": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", + "integrity": "sha1-rdV8jXzHOoFjDTHNVdOWHPr7qcM=", + "dev": true, + "requires": { + "commander": "^2.2.0", + "limiter": "^1.0.5" + } + }, + "streamfilter": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.7.tgz", + "integrity": "sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ==", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "string-argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", + "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", + "dev": true + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", + "dev": true, + "requires": { + "first-chunk-stream": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "strip-comments": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-1.0.2.tgz", + "integrity": "sha512-kL97alc47hoyIQSV165tTt9rG5dn4w1dNnBhOQ3bOU1Nc1hel09jnXANaHJ7vzHLd4Ju8kseDGzlev96pghLFw==", + "dev": true, + "requires": { + "babel-extract-comments": "^1.0.0", + "babel-plugin-transform-object-rest-spread": "^6.26.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "style-loader": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" + } + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz", + "integrity": "sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=", + "dev": true, + "requires": { + "dot-prop": "^4.1.1", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "svgo": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.2.0.tgz", + "integrity": "sha512-xBfxJxfk4UeVN8asec9jNxHiv3UAMv/ujwBWGYvQhhMb2u3YTGKkiybPcLFDLq7GLLWE9wa73e0/m8L5nTzQbw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.28", + "css-url-regex": "^1.1.0", + "csso": "^3.5.1", + "js-yaml": "^3.12.0", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "css-select": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz", + "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^2.1.2", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "swagger-ui": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/swagger-ui/-/swagger-ui-2.2.10.tgz", + "integrity": "sha1-sl56IWZOXZC/OR2zDbCN5B6FLXs=" + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", + "dev": true + }, + "synchronous-promise": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.6.tgz", + "integrity": "sha512-TyOuWLwkmtPL49LHCX1caIwHjRzcVd62+GF6h8W/jHOeZUFHpnd2XJDVuUlaTaLPH1nuu2M69mfHr5XbQJnf/g==", + "dev": true + }, + "tabtab": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tabtab/-/tabtab-2.2.2.tgz", + "integrity": "sha1-egR/FDsBC0y9MfhX6ClhUSy/ThQ=", + "dev": true, + "requires": { + "debug": "^2.2.0", + "inquirer": "^1.0.2", + "lodash.difference": "^4.5.0", + "lodash.uniq": "^4.5.0", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "npmlog": "^2.0.3", + "object-assign": "^4.1.0" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "external-editor": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-1.1.1.tgz", + "integrity": "sha1-Etew24UPf/fnCBuvQAVwAGDEYAs=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "spawn-sync": "^1.0.15", + "tmp": "^0.0.29" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "inquirer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-1.2.3.tgz", + "integrity": "sha1-TexvMvN+97sLLtPx0aXD9UUHSRg=", + "dev": true, + "requires": { + "ansi-escapes": "^1.1.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "external-editor": "^1.1.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "mute-stream": "0.0.6", + "pinkie-promise": "^2.0.0", + "run-async": "^2.2.0", + "rx": "^4.1.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "mute-stream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz", + "integrity": "sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s=", + "dev": true + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "tmp": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz", + "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + } + } + }, + "tapable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", + "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", + "dev": true + }, + "tar": { + "version": "4.4.8", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "terser": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", + "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.10" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.2.tgz", + "integrity": "sha512-1DMkTk286BzmfylAvLXwpJrI7dWa5BnFmscV/2dCr8+c56egFcbaeFAl7+sujAjdmpLam21XRdhA4oifLyiWWg==", + "dev": true, + "requires": { + "cacache": "^11.0.2", + "find-cache-dir": "^2.0.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.4.0", + "source-map": "^0.6.1", + "terser": "^3.16.1", + "webpack-sources": "^1.1.0", + "worker-farm": "^1.5.2" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "test-exclude": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.1.0.tgz", + "integrity": "sha512-gwf0S2fFsANC55fSeSqpb8BYk6w3FDvwZxfNjeF6FRgvFa43r+7wRiA/Q0IxoRU37wB/LE8IQ4221BsNucTaCA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^1.0.1" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + } + } + }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "textextensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.4.0.tgz", + "integrity": "sha512-qftQXnX1DzpSV8EddtHIT0eDDEiBF8ywhFYR2lI9xrGtxqKN+CvLXhACeCIGbCpQfxxERbrkZEFb8cZcDKbVZA==", + "dev": true + }, + "tfunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tfunk/-/tfunk-3.1.0.tgz", + "integrity": "sha1-OORBT8ZJd9h6/apy+sttKfgve1s=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "object-path": "^0.9.0" + } + }, + "thread-loader": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-2.1.2.tgz", + "integrity": "sha512-7xpuc9Ifg6WU+QYw/8uUqNdRwMD+N5gjwHKMqETrs96Qn+7BHwECpt2Brzr4HFlf4IAkZsayNhmGdbkBsTJ//w==", + "dev": true, + "requires": { + "loader-runner": "^2.3.1", + "loader-utils": "^1.1.0", + "neo-async": "^2.6.0" + } + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", + "dev": true + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "to-string-loader": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/to-string-loader/-/to-string-loader-1.1.5.tgz", + "integrity": "sha1-e3qheJG3u0lHp6Eb+wO1/enG5pU=", + "dev": true, + "requires": { + "loader-utils": "^0.2.16" + }, + "dependencies": { + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + } + } + }, + "topo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", + "dev": true, + "requires": { + "hoek": "4.x.x" + } + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "dev": true + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", + "dev": true + }, + "ts-jest": { + "version": "23.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-23.1.4.tgz", + "integrity": "sha512-9rCSxbWfoZxxeXnSoEIzRNr9hDIQ8iEJAWmSRsWhDHDT8OeuGfURhJQUE8jtJlkyEygs6rngH8RYtHz9cfjmEA==", + "dev": true, + "requires": { + "closest-file-data": "^0.1.4", + "fs-extra": "6.0.1", + "json5": "^0.5.0", + "lodash": "^4.17.10" + }, + "dependencies": { + "fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + } + } + }, + "ts-loader": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-5.3.3.tgz", + "integrity": "sha512-KwF1SplmOJepnoZ4eRIloH/zXL195F51skt7reEsS6jvDqzgc/YSbz9b8E07GxIUwLXdcD4ssrJu6v8CwaTafA==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^3.1.4", + "semver": "^5.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "tslint": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.12.1.tgz", + "integrity": "sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.27.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "tslint-config-prettier": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", + "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", + "dev": true + }, + "tslint-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tslint-loader/-/tslint-loader-3.6.0.tgz", + "integrity": "sha512-Me9Qf/87BOfCY8uJJw+J7VMF4U8WiMXKLhKKKugMydF0xMhMOt9wo2mjYTNhwbF9H7SHh8PAIwRG8roisTNekQ==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.1", + "rimraf": "^2.4.4", + "semver": "^5.3.0" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", + "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.17", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", + "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==", + "dev": true + }, + "uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", + "dev": true, + "requires": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", + "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==", + "dev": true + }, + "upath": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", + "dev": true + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", + "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", + "dev": true, + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", + "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vendors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", + "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.3.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^2.0.0", + "vinyl": "^1.1.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "webpack": { + "version": "4.29.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.3.tgz", + "integrity": "sha512-xPJvFeB+8tUflXFq+OgdpiSnsCD5EANyv56co5q8q8+YtEasn5Sj3kzY44mta+csCIEB0vneSxnuaHkOL2h94A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/wasm-edit": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "acorn": "^6.0.5", + "acorn-dynamic-import": "^4.0.0", + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chrome-trace-event": "^1.0.0", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.0", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.3.0", + "loader-utils": "^1.1.0", + "memory-fs": "~0.4.1", + "micromatch": "^3.1.8", + "mkdirp": "~0.5.0", + "neo-async": "^2.5.0", + "node-libs-browser": "^2.0.0", + "schema-utils": "^1.0.0", + "tapable": "^1.1.0", + "terser-webpack-plugin": "^1.1.0", + "watchpack": "^1.5.0", + "webpack-sources": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + } + } + }, + "webpack-cli": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.2.3.tgz", + "integrity": "sha512-Ik3SjV6uJtWIAN5jp5ZuBMWEAaP5E4V78XJ2nI+paFPh8v4HPSwo/myN0r29Xc/6ZKnd2IdrAlpSgNOu2CDQ6Q==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.0", + "findup-sync": "^2.0.0", + "global-modules": "^1.0.0", + "import-local": "^2.0.0", + "interpret": "^1.1.0", + "loader-utils": "^1.1.0", + "supports-color": "^5.5.0", + "v8-compile-cache": "^2.0.2", + "yargs": "^12.0.4" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz", + "integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz", + "integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz", + "integrity": "sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==", + "dev": true, + "requires": { + "memory-fs": "~0.4.1", + "mime": "^2.3.1", + "range-parser": "^1.0.3", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "dev": true + } + } + }, + "webpack-dev-server": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz", + "integrity": "sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.0.0", + "compression": "^1.5.2", + "connect-history-api-fallback": "^1.3.0", + "debug": "^3.1.0", + "del": "^3.0.0", + "express": "^4.16.2", + "html-entities": "^1.2.0", + "http-proxy-middleware": "~0.18.0", + "import-local": "^2.0.0", + "internal-ip": "^3.0.1", + "ip": "^1.1.5", + "killable": "^1.0.0", + "loglevel": "^1.4.1", + "opn": "^5.1.0", + "portfinder": "^1.0.9", + "schema-utils": "^1.0.0", + "selfsigned": "^1.9.1", + "semver": "^5.6.0", + "serve-index": "^1.7.2", + "sockjs": "0.3.19", + "sockjs-client": "1.3.0", + "spdy": "^4.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^5.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "3.4.0", + "webpack-log": "^2.0.0", + "yargs": "12.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", + "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "dev": true, + "requires": { + "xregexp": "4.0.0" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mem": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz", + "integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz", + "integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", + "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^2.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^10.1.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-merge": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", + "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", + "dev": true, + "requires": { + "lodash": "^4.17.5" + } + }, + "webpack-notifier": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/webpack-notifier/-/webpack-notifier-1.7.0.tgz", + "integrity": "sha512-L3UKrl500xk0VDYKkwQxy5/BPhBWsZ2xHsAx2Qe3dVKYUEk9+y690RcNTMIUcVOK2fRgK7KK3PA4ccOq1h+fTg==", + "dev": true, + "requires": { + "node-notifier": "^5.1.2", + "object-assign": "^4.1.0", + "strip-ansi": "^3.0.1" + } + }, + "webpack-sources": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webpack-visualizer-plugin": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/webpack-visualizer-plugin/-/webpack-visualizer-plugin-0.1.11.tgz", + "integrity": "sha1-uHcK2GtPZSYSxosbeCJT+vn4o04=", + "dev": true, + "requires": { + "d3": "^3.5.6", + "mkdirp": "^0.5.1", + "react": "^0.14.0", + "react-dom": "^0.14.0" + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-fetch": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz", + "integrity": "sha1-DjaExsuZlbQ+/J3wPkw2XZX9nMA=", + "dev": true + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "win-release": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", + "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", + "dev": true, + "requires": { + "semver": "^5.0.1" + } + }, + "window-size": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", + "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=", + "dev": true + }, + "winston": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", + "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", + "dev": true, + "requires": { + "async": "^2.6.1", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^2.1.1", + "one-time": "0.0.4", + "readable-stream": "^3.1.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.3.0" + }, + "dependencies": { + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "readable-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "winston-transport": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", + "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "dev": true, + "requires": { + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "workbox-background-sync": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-3.6.3.tgz", + "integrity": "sha512-ypLo0B6dces4gSpaslmDg5wuoUWrHHVJfFWwl1udvSylLdXvnrfhFfriCS42SNEe5lsZtcNZF27W/SMzBlva7Q==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-broadcast-cache-update": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-broadcast-cache-update/-/workbox-broadcast-cache-update-3.6.3.tgz", + "integrity": "sha512-pJl4lbClQcvp0SyTiEw0zLSsVYE1RDlCPtpKnpMjxFtu8lCFTAEuVyzxp9w7GF4/b3P4h5nyQ+q7V9mIR7YzGg==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-build": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-3.6.3.tgz", + "integrity": "sha512-w0clZ/pVjL8VXy6GfthefxpEXs0T8uiRuopZSFVQ8ovfbH6c6kUpEh6DcYwm/Y6dyWPiCucdyAZotgjz+nRz8g==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "common-tags": "^1.4.0", + "fs-extra": "^4.0.2", + "glob": "^7.1.2", + "joi": "^11.1.1", + "lodash.template": "^4.4.0", + "pretty-bytes": "^4.0.2", + "stringify-object": "^3.2.2", + "strip-comments": "^1.0.2", + "workbox-background-sync": "^3.6.3", + "workbox-broadcast-cache-update": "^3.6.3", + "workbox-cache-expiration": "^3.6.3", + "workbox-cacheable-response": "^3.6.3", + "workbox-core": "^3.6.3", + "workbox-google-analytics": "^3.6.3", + "workbox-navigation-preload": "^3.6.3", + "workbox-precaching": "^3.6.3", + "workbox-range-requests": "^3.6.3", + "workbox-routing": "^3.6.3", + "workbox-strategies": "^3.6.3", + "workbox-streams": "^3.6.3", + "workbox-sw": "^3.6.3" + }, + "dependencies": { + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", + "dev": true + } + } + }, + "workbox-cache-expiration": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-cache-expiration/-/workbox-cache-expiration-3.6.3.tgz", + "integrity": "sha512-+ECNph/6doYx89oopO/UolYdDmQtGUgo8KCgluwBF/RieyA1ZOFKfrSiNjztxOrGJoyBB7raTIOlEEwZ1LaHoA==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-cacheable-response": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-3.6.3.tgz", + "integrity": "sha512-QpmbGA9SLcA7fklBLm06C4zFg577Dt8u3QgLM0eMnnbaVv3rhm4vbmDpBkyTqvgK/Ly8MBDQzlXDtUCswQwqqg==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-core": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-3.6.3.tgz", + "integrity": "sha512-cx9cx0nscPkIWs8Pt98HGrS9/aORuUcSkWjG25GqNWdvD/pSe7/5Oh3BKs0fC+rUshCiyLbxW54q0hA+GqZeSQ==", + "dev": true + }, + "workbox-google-analytics": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-3.6.3.tgz", + "integrity": "sha512-RQBUo/6SXtIaQTRFj4RQZ9e1gAl7D8oS5S+Hi173Kk70/BgJjzPwXpC5A249Jv5YfkCOLMQCeF9A27BiD0b0ig==", + "dev": true, + "requires": { + "workbox-background-sync": "^3.6.3", + "workbox-core": "^3.6.3", + "workbox-routing": "^3.6.3", + "workbox-strategies": "^3.6.3" + } + }, + "workbox-navigation-preload": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-3.6.3.tgz", + "integrity": "sha512-dd26xTX16DUu0i+MhqZK/jQXgfIitu0yATM4jhRXEmpMqQ4MxEeNvl2CgjDMOHBnCVMax+CFZQWwxMx/X/PqCw==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-precaching": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-3.6.3.tgz", + "integrity": "sha512-aBqT66BuMFviPTW6IpccZZHzpA8xzvZU2OM1AdhmSlYDXOJyb1+Z6blVD7z2Q8VNtV1UVwQIdImIX+hH3C3PIw==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-range-requests": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-3.6.3.tgz", + "integrity": "sha512-R+yLWQy7D9aRF9yJ3QzwYnGFnGDhMUij4jVBUVtkl67oaVoP1ymZ81AfCmfZro2kpPRI+vmNMfxxW531cqdx8A==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-routing": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-3.6.3.tgz", + "integrity": "sha512-bX20i95OKXXQovXhFOViOK63HYmXvsIwZXKWbSpVeKToxMrp0G/6LZXnhg82ijj/S5yhKNRf9LeGDzaqxzAwMQ==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-strategies": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-3.6.3.tgz", + "integrity": "sha512-Pg5eulqeKet2y8j73Yw6xTgLdElktcWExGkzDVCGqfV9JCvnGuEpz5eVsCIK70+k4oJcBCin9qEg3g3CwEIH3g==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-streams": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-3.6.3.tgz", + "integrity": "sha512-rqDuS4duj+3aZUYI1LsrD2t9hHOjwPqnUIfrXSOxSVjVn83W2MisDF2Bj+dFUZv4GalL9xqErcFW++9gH+Z27w==", + "dev": true, + "requires": { + "workbox-core": "^3.6.3" + } + }, + "workbox-sw": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-3.6.3.tgz", + "integrity": "sha512-IQOUi+RLhvYCiv80RP23KBW/NTtIvzvjex28B8NW1jOm+iV4VIu3VXKXTA6er5/wjjuhmtB28qEAUqADLAyOSg==", + "dev": true + }, + "workbox-webpack-plugin": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-3.6.3.tgz", + "integrity": "sha512-RwmKjc7HFHUFHoOlKoZUq9349u0QN3F8W5tZZU0vc1qsBZDINWXRiIBCAKvo/Njgay5sWz7z4I2adnyTo97qIQ==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "json-stable-stringify": "^1.0.1", + "workbox-build": "^3.6.3" + } + }, + "worker-farm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", + "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", + "integrity": "sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "write-file-webpack-plugin": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/write-file-webpack-plugin/-/write-file-webpack-plugin-4.5.0.tgz", + "integrity": "sha512-k46VeERtaezbmjpDcMWATjKUWBrVe/ZEEm0cyvUm8FFP8A/r+dw5x3psRvkUOhqh9bqBLUlGYYbtr6luI+HeAg==", + "dev": true, + "requires": { + "chalk": "^2.4.0", + "debug": "^3.1.0", + "filesize": "^3.6.1", + "lodash": "^4.17.5", + "mkdirp": "^0.5.1", + "moment": "^2.22.1", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "ws": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", + "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", + "dev": true + }, + "xregexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, + "dependencies": { + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", + "dev": true + }, + "yeoman-environment": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.3.0.tgz", + "integrity": "sha512-PHSAkVOqYdcR+C+Uht1SGC4eVD/9OhygYFkYaI66xF8vKIeS1RNYay+umj2ZrQeJ50tF5Q/RSO6qGDz9y3Ifug==", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^3.1.0", + "diff": "^3.3.1", + "escape-string-regexp": "^1.0.2", + "globby": "^8.0.1", + "grouped-queue": "^0.3.3", + "inquirer": "^5.2.0", + "is-scoped": "^1.0.0", + "lodash": "^4.17.10", + "log-symbols": "^2.1.0", + "mem-fs": "^1.1.0", + "strip-ansi": "^4.0.0", + "text-table": "^0.2.0", + "untildify": "^3.0.2" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "path-type": "^3.0.0" + } + }, + "globby": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", + "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "2.0.0", + "fast-glob": "^2.0.2", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + } + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.1.0", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^5.5.2", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + } + } + }, + "yeoman-generator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-3.0.0.tgz", + "integrity": "sha512-aHsNXzkdgAoakZTZsDX7T56wYWYd1O5E/GBIFAVMJLH7TKRr+1MiEJszZQbbCSA+J+lpT743/8L88j35yNdTLQ==", + "dev": true, + "requires": { + "async": "^2.6.0", + "chalk": "^2.3.0", + "cli-table": "^0.3.1", + "cross-spawn": "^6.0.5", + "dargs": "^6.0.0", + "dateformat": "^3.0.3", + "debug": "^3.1.0", + "detect-conflict": "^1.0.0", + "error": "^7.0.2", + "find-up": "^3.0.0", + "github-username": "^4.0.0", + "istextorbinary": "^2.2.1", + "lodash": "^4.17.10", + "make-dir": "^1.1.0", + "mem-fs-editor": "^5.0.0", + "minimist": "^1.2.0", + "pretty-bytes": "^5.1.0", + "read-chunk": "^2.1.0", + "read-pkg-up": "^4.0.0", + "rimraf": "^2.6.2", + "run-async": "^2.0.0", + "shelljs": "^0.8.0", + "text-table": "^0.2.0", + "through2": "^2.0.0", + "yeoman-environment": "^2.0.5" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "yup": { + "version": "0.26.10", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.26.10.tgz", + "integrity": "sha512-keuNEbNSnsOTOuGCt3UJW69jDE3O4P+UHAakO7vSeFMnjaitcmlbij/a3oNb9g1Y1KvSKH/7O1R2PQ4m4TRylw==", + "dev": true, + "requires": { + "@babel/runtime": "7.0.0", + "fn-name": "~2.0.1", + "lodash": "^4.17.10", + "property-expr": "^1.5.0", + "synchronous-promise": "^2.0.5", + "toposort": "^2.0.2" + }, + "dependencies": { + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", + "dev": true + } + } + }, + "zone.js": { + "version": "0.8.29", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.29.tgz", + "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==" + } + } +} diff --git a/jhipster-5/bookstore-monolith/package.json b/jhipster-5/bookstore-monolith/package.json new file mode 100644 index 0000000000..46b920edb3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/package.json @@ -0,0 +1,128 @@ +{ + "name": "bookstore", + "version": "0.0.0", + "description": "Description for Bookstore", + "private": true, + "license": "UNLICENSED", + "cacheDirectories": [ + "node_modules" + ], + "dependencies": { + "@angular/common": "7.2.4", + "@angular/compiler": "7.2.4", + "@angular/core": "7.2.4", + "@angular/forms": "7.2.4", + "@angular/platform-browser": "7.2.4", + "@angular/platform-browser-dynamic": "7.2.4", + "@angular/router": "7.2.4", + "@fortawesome/angular-fontawesome": "0.3.0", + "@fortawesome/fontawesome-svg-core": "1.2.14", + "@fortawesome/free-solid-svg-icons": "5.7.1", + "@ng-bootstrap/ng-bootstrap": "4.0.2", + "@ngx-translate/core": "11.0.1", + "@ngx-translate/http-loader": "4.0.0", + "bootstrap": "4.2.1", + "core-js": "2.6.4", + "moment": "2.24.0", + "ng-jhipster": "0.9.1", + "ngx-cookie": "2.0.1", + "ngx-infinite-scroll": "7.0.1", + "ngx-webstorage": "2.0.1", + "rxjs": "6.4.0", + "swagger-ui": "2.2.10", + "tslib": "1.9.3", + "zone.js": "0.8.29" + }, + "devDependencies": { + "@angular/cli": "7.3.1", + "@angular/compiler-cli": "7.2.4", + "@ngtools/webpack": "7.3.1", + "@types/jest": "24.0.0", + "@types/node": "10.12.24", + "angular-router-loader": "0.8.5", + "angular2-template-loader": "0.6.2", + "autoprefixer": "9.4.7", + "browser-sync": "2.26.3", + "browser-sync-webpack-plugin": "2.2.2", + "cache-loader": "2.0.1", + "codelyzer": "4.5.0", + "copy-webpack-plugin": "4.6.0", + "css-loader": "2.1.0", + "file-loader": "3.0.1", + "fork-ts-checker-webpack-plugin": "0.5.2", + "friendly-errors-webpack-plugin": "1.7.0", + "generator-jhipster": "5.8.2", + "html-loader": "0.5.5", + "html-webpack-plugin": "3.2.0", + "husky": "1.3.1", + "jest": "24.1.0", + "jest-junit": "6.2.1", + "jest-preset-angular": "6.0.2", + "jest-sonar-reporter": "2.0.0", + "lint-staged": "8.1.3", + "mini-css-extract-plugin": "0.5.0", + "moment-locales-webpack-plugin": "1.0.7", + "optimize-css-assets-webpack-plugin": "5.0.1", + "prettier": "1.16.4", + "reflect-metadata": "0.1.13", + "rimraf": "2.6.3", + "simple-progress-webpack-plugin": "1.1.2", + "style-loader": "0.23.1", + "terser-webpack-plugin": "1.2.2", + "thread-loader": "2.1.2", + "to-string-loader": "1.1.5", + "ts-loader": "5.3.3", + "tslint": "5.12.1", + "tslint-config-prettier": "1.18.0", + "tslint-loader": "3.6.0", + "typescript": "3.2.4", + "sass": "1.17.0", + "sass-loader": "7.1.0", + "postcss-loader": "3.0.0", + "xml2js": "0.4.19", + "webpack": "4.29.3", + "webpack-cli": "3.2.3", + "webpack-dev-server": "3.1.14", + "webpack-merge": "4.2.1", + "webpack-notifier": "1.7.0", + "webpack-visualizer-plugin": "0.1.11", + "workbox-webpack-plugin": "3.6.3", + "write-file-webpack-plugin": "4.5.0" + }, + "engines": { + "node": ">=8.9.0" + }, + "lint-staged": { + "{,src/**/}*.{md,json,ts,css,scss}": [ + "prettier --write", + "git add" + ] + }, + "scripts": { + "prettier:format": "prettier --write \"{,src/**/}*.{md,json,ts,css,scss}\"", + "lint": "tslint --project tsconfig.json -e 'node_modules/**'", + "lint:fix": "npm run lint -- --fix", + "ngc": "ngc -p tsconfig-aot.json", + "cleanup": "rimraf target/{aot,www}", + "clean-www": "rimraf target//www/app/{src,target/}", + "start": "npm run webpack:dev", + "start-tls": "npm run webpack:dev -- --env.tls", + "serve": "npm run start", + "build": "npm run webpack:prod", + "test": "npm run lint && jest --coverage --logHeapUsage -w=2 --config src/test/javascript/jest.conf.js", + "test:watch": "npm run test -- --watch", + "webpack:dev": "npm run webpack-dev-server -- --config webpack/webpack.dev.js --inline --hot --port=9060 --watch-content-base --env.stats=minimal", + "webpack:dev-verbose": "npm run webpack-dev-server -- --config webpack/webpack.dev.js --inline --hot --port=9060 --watch-content-base --profile --progress --env.stats=normal", + "webpack:build:main": "npm run webpack -- --config webpack/webpack.dev.js --env.stats=minimal", + "webpack:build": "npm run cleanup && npm run webpack:build:main", + "webpack:prod:main": "npm run webpack -- --config webpack/webpack.prod.js --profile", + "webpack:prod": "npm run cleanup && npm run webpack:prod:main && npm run clean-www", + "webpack:test": "npm run test", + "webpack-dev-server": "node --max_old_space_size=4096 node_modules/webpack-dev-server/bin/webpack-dev-server.js", + "webpack": "node --max_old_space_size=4096 node_modules/webpack/bin/webpack.js" + }, + "jestSonar": { + "reportPath": "target/test-results/jest", + "reportFile": "TESTS-results-sonar.xml" + } +} diff --git a/jhipster-5/bookstore-monolith/pom.xml b/jhipster-5/bookstore-monolith/pom.xml new file mode 100644 index 0000000000..e46804a04c --- /dev/null +++ b/jhipster-5/bookstore-monolith/pom.xml @@ -0,0 +1,1085 @@ + + + 4.0.0 + + com.baeldung.jhipster5 + bookstore + 0.0.1-SNAPSHOT + war + Bookstore + + + + + + + + + + + + + + 3.0.0 + 1.8 + 2.12.6 + v10.15.0 + 6.4.1 + UTF-8 + UTF-8 + ${project.build.directory}/test-results + yyyyMMddHHmmss + ${java.version} + ${java.version} + -Djava.security.egd=file:/dev/./urandom -Xmx256m + jdt_apt + false + + + + + + + 2.1.1 + + 2.0.8.RELEASE + + 5.2.17.Final + + 3.22.0-GA + + 3.5.5 + 3.6 + 2.0.1.Final + 1.2.0.Final + + + 3.1.0 + 3.8.0 + 2.10 + 3.0.0-M2 + 2.2.1 + 3.1.0 + 2.22.1 + 3.2.2 + 0.9.11 + 1.6 + 0.8.2 + 1.0.0 + 3.4.2 + 3.5.0.1254 + 2.2.5 + + + http://localhost:9001 + src/main/webapp/content/**/*.*, src/main/webapp/i18n/*.js, target/www/**/*.* + S3437,S4502,S4684,UndocumentedApi,BoldAndItalicTagsCheck + + src/main/webapp/app/**/*.* + Web:BoldAndItalicTagsCheck + + src/main/java/**/* + squid:S3437 + + src/main/java/**/* + squid:UndocumentedApi + + src/main/java/**/* + squid:S4502 + + src/main/java/**/* + squid:S4684 + ${project.testresult.directory}/coverage/jacoco/jacoco.exec + jacoco + ${project.testresult.directory}/lcov.info + ${project.basedir}/src/main/ + ${project.testresult.directory} + ${project.basedir}/src/test/ + + + + + + + + io.github.jhipster + jhipster-dependencies + ${jhipster-dependencies.version} + pom + import + + + + + + + + io.github.jhipster + jhipster-framework + + + + com.fasterxml.jackson.datatype + jackson-datatype-hibernate5 + + + com.fasterxml.jackson.datatype + jackson-datatype-hppc + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + com.fasterxml.jackson.module + jackson-module-afterburner + + + com.h2database + h2 + test + + + com.jayway.jsonpath + json-path + test + + + + io.springfox + springfox-swagger2 + + + io.springfox + springfox-bean-validators + + + com.mattbertolini + liquibase-slf4j + + + com.zaxxer + HikariCP + + + commons-io + commons-io + + + org.apache.commons + commons-lang3 + + + mysql + mysql-connector-java + + + org.assertj + assertj-core + test + + + org.hibernate + hibernate-jpamodelgen + provided + + + org.hibernate + hibernate-envers + + + org.hibernate.validator + hibernate-validator + + + org.liquibase + liquibase-core + + + net.logstash.logback + logstash-logback-encoder + + + org.mapstruct + mapstruct-jdk8 + + + org.mapstruct + mapstruct-processor + provided + + + org.springframework.boot + spring-boot-configuration-processor + provided + + + org.springframework.boot + spring-boot-loader-tools + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework.boot + spring-boot-starter-mail + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-test + test + + + org.springframework.security + spring-security-test + test + + + org.zalando + problem-spring-web + + + io.jsonwebtoken + jjwt-api + + + io.jsonwebtoken + jjwt-impl + runtime + + + io.jsonwebtoken + jjwt-jackson + runtime + + + + org.springframework.boot + spring-boot-starter-cloud-connectors + + + + org.springframework.security + spring-security-data + + + io.micrometer + micrometer-registry-prometheus + + + io.dropwizard.metrics + metrics-core + + + + + + spring-boot:run + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + + org.hibernate + hibernate-jpamodelgen + ${hibernate.version} + + + + + + + org.apache.maven.plugins + maven-eclipse-plugin + + + org.apache.maven.plugins + maven-enforcer-plugin + + + org.apache.maven.plugins + maven-idea-plugin + + + org.apache.maven.plugins + maven-resources-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.jacoco + jacoco-maven-plugin + + + org.sonarsource.scanner.maven + sonar-maven-plugin + + + org.liquibase + liquibase-maven-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + ${start-class} + true + true + + + + + com.google.cloud.tools + jib-maven-plugin + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + com.github.eirslett + frontend-maven-plugin + ${frontend-maven-plugin.version} + + + pl.project13.maven + git-commit-id-plugin + ${git-commit-id-plugin.version} + + + + revision + + + + + false + true + + ^git.commit.id.abbrev$ + ^git.commit.id.describe$ + ^git.branch$ + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco-maven-plugin.version} + + + pre-unit-tests + + prepare-agent + + + + ${project.testresult.directory}/coverage/jacoco/jacoco.exec + + + + + post-unit-test + test + + report + + + ${project.testresult.directory}/coverage/jacoco/jacoco.exec + ${project.testresult.directory}/coverage/jacoco + + + + + + com.google.cloud.tools + jib-maven-plugin + ${jib-maven-plugin.version} + + + openjdk:8-jre-alpine + + + bookstore:latest + + + + sh + + chmod +x /entrypoint.sh && sync && /entrypoint.sh + + + 8080 + + + ALWAYS + 0 + + true + + + + + org.liquibase + liquibase-maven-plugin + ${liquibase.version} + + ${project.basedir}/src/main/resources/config/liquibase/master.xml + ${project.basedir}/src/main/resources/config/liquibase/changelog/${maven.build.timestamp}_changelog.xml + + + + Bookstore + + hibernate:spring:com.baeldung.jhipster5.domain?dialect=&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy + true + debug + + + + org.javassist + javassist + ${javassist.version} + + + org.liquibase.ext + liquibase-hibernate5 + ${liquibase-hibernate5.version} + + + org.springframework.boot + spring-boot-starter-data-jpa + ${spring-boot.version} + + + javax.validation + validation-api + ${validation-api.version} + + + + + maven-clean-plugin + ${maven-clean-plugin.version} + + + org.apache.maven.plugins + maven-eclipse-plugin + ${maven-eclipse-plugin.version} + + true + true + + + + org.apache.maven.plugins + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + enforce-versions + + enforce + + + + + + + You are running an older version of Maven. JHipster requires at least Maven ${maven.version} + [${maven.version},) + + + + You are running an incompatible version of Java. JHipster requires JDK ${java.version} + [1.8,1.9) + + + + + + org.apache.maven.plugins + maven-idea-plugin + ${maven-idea-plugin.version} + + node_modules + + + + org.apache.maven.plugins + maven-resources-plugin + ${maven-resources-plugin.version} + + + default-resources + validate + + copy-resources + + + ${project.build.directory}/classes + false + + # + + + + src/main/resources/ + true + + config/*.yml + + + + src/main/resources/ + false + + config/*.yml + + + + + + + jib-www-resources + verify + + copy-resources + + + ${project.build.directory}/classes/static/ + + + ${project.build.directory}/www + false + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + alphabetical + + + false + ${sonar.junit.reportsPath} + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + net.alchim31.maven + scala-maven-plugin + ${scala-maven-plugin.version} + + + compile + compile + + add-source + compile + + + + test-compile + test-compile + + add-source + testCompile + + + + + incremental + true + ${scala.version} + + + + org.sonarsource.scanner.maven + sonar-maven-plugin + ${sonar-maven-plugin.version} + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + + + + no-liquibase + + ,no-liquibase + + + + swagger + + ,swagger + + + + tls + + ,tls + + + + webpack + + + ${basedir}/target/www/app/main.bundle.js + + + + + org.springframework.boot + spring-boot-starter-undertow + + + org.springframework.boot + spring-boot-devtools + true + + + com.h2database + h2 + + + + + + com.github.eirslett + frontend-maven-plugin + + + install node and npm + + install-node-and-npm + + + ${node.version} + ${npm.version} + + + + npm install + + npm + + + + webpack build dev + + npm + + generate-resources + + run webpack:build + false + + + + + + org.apache.maven.plugins + maven-war-plugin + + false + target/www/ + + + src/main/webapp + + WEB-INF/** + + + + + + + + + + dev${profile.no-liquibase} + + + + dev + + true + + + + org.springframework.boot + spring-boot-starter-undertow + + + org.springframework.boot + spring-boot-devtools + true + + + com.h2database + h2 + + + + + + org.apache.maven.plugins + maven-war-plugin + + false + target/www/ + + + src/main/webapp + + WEB-INF/** + + + + + + + + + + dev${profile.tls}${profile.no-liquibase} + + + + prod + + + org.springframework.boot + spring-boot-starter-undertow + + + + + + maven-clean-plugin + + + + target/www/ + + + + + + org.apache.maven.plugins + maven-war-plugin + + false + target/www/ + + + src/main/webapp + + WEB-INF/** + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + ${start-class} + true + + + + + build-info + + + + + + com.github.eirslett + frontend-maven-plugin + + + install node and npm + + install-node-and-npm + + + ${node.version} + ${npm.version} + + + + npm install + + npm + + + install + + + + webpack build test + + npm + + test + + run webpack:test + false + + + + webpack build prod + + npm + + generate-resources + + run webpack:prod + false + + + + + + pl.project13.maven + git-commit-id-plugin + + + + + + prod${profile.swagger}${profile.no-liquibase} + + + + + cc + + + org.springframework.boot + spring-boot-starter-undertow + + + org.springframework.boot + spring-boot-devtools + true + + + + + + org.apache.maven.plugins + maven-war-plugin + + false + src/main/webapp/ + + + + org.springframework.boot + spring-boot-maven-plugin + + ${start-class} + true + true + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + default-compile + none + + + default-testCompile + none + + + + + net.alchim31.maven + scala-maven-plugin + + + + + + dev,swagger + + + + + IDE + + + org.mapstruct + mapstruct-processor + + + org.hibernate + hibernate-jpamodelgen + + + + + + eclipse + + + m2e.version + + + + + + + + org.eclipse.m2e + lifecycle-mapping + ${lifecycle-mapping.version} + + + + + + org.jacoco + + jacoco-maven-plugin + + + ${jacoco-maven-plugin.version} + + + prepare-agent + + + + + + + + + com.github.eirslett + frontend-maven-plugin + ${frontend-maven-plugin.version} + + install-node-and-npm + npm + + + + + + + + + + + + + + + + + diff --git a/jhipster-5/bookstore-monolith/postcss.config.js b/jhipster-5/bookstore-monolith/postcss.config.js new file mode 100644 index 0000000000..a26de7e9f1 --- /dev/null +++ b/jhipster-5/bookstore-monolith/postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: [ + require('autoprefixer') + ] +} diff --git a/jhipster-5/bookstore-monolith/proxy.conf.json b/jhipster-5/bookstore-monolith/proxy.conf.json new file mode 100644 index 0000000000..8b41fdf7fa --- /dev/null +++ b/jhipster-5/bookstore-monolith/proxy.conf.json @@ -0,0 +1,7 @@ +{ + "*": { + "target": "http://localhost:8080", + "secure": false, + "loglevel": "debug" + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/docker/.dockerignore b/jhipster-5/bookstore-monolith/src/main/docker/.dockerignore new file mode 100644 index 0000000000..b03bdc71ee --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/docker/.dockerignore @@ -0,0 +1,14 @@ +# https://docs.docker.com/engine/reference/builder/#dockerignore-file +classes/ +generated-sources/ +generated-test-sources/ +h2db/ +maven-archiver/ +maven-status/ +reports/ +surefire-reports/ +test-classes/ +test-results/ +www/ +!*.jar +!*.war diff --git a/jhipster-5/bookstore-monolith/src/main/docker/Dockerfile b/jhipster-5/bookstore-monolith/src/main/docker/Dockerfile new file mode 100644 index 0000000000..43fadcb6f8 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/docker/Dockerfile @@ -0,0 +1,20 @@ +FROM openjdk:8-jre-alpine + +ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \ + JHIPSTER_SLEEP=0 \ + JAVA_OPTS="" + +# Add a jhipster user to run our application so that it doesn't need to run as root +RUN adduser -D -s /bin/sh jhipster +WORKDIR /home/jhipster + +ADD entrypoint.sh entrypoint.sh +RUN chmod 755 entrypoint.sh && chown jhipster:jhipster entrypoint.sh +USER jhipster + +ENTRYPOINT ["./entrypoint.sh"] + +EXPOSE 8080 + +ADD *.war app.war + diff --git a/jhipster-5/bookstore-monolith/src/main/docker/app.yml b/jhipster-5/bookstore-monolith/src/main/docker/app.yml new file mode 100644 index 0000000000..f60f0f5038 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/docker/app.yml @@ -0,0 +1,15 @@ +version: '2' +services: + bookstore-app: + image: bookstore + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=prod,swagger + - SPRING_DATASOURCE_URL=jdbc:mysql://bookstore-mysql:3306/bookstore?useUnicode=true&characterEncoding=utf8&useSSL=false + - JHIPSTER_SLEEP=10 # gives time for the database to boot before the application + ports: + - 8080:8080 + bookstore-mysql: + extends: + file: mysql.yml + service: bookstore-mysql diff --git a/jhipster-5/bookstore-monolith/src/main/docker/entrypoint.sh b/jhipster-5/bookstore-monolith/src/main/docker/entrypoint.sh new file mode 100644 index 0000000000..ccffafb5a4 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/docker/entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "The application will start in ${JHIPSTER_SLEEP}s..." && sleep ${JHIPSTER_SLEEP} +exec java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar "${HOME}/app.war" "$@" diff --git a/jhipster-5/bookstore-monolith/src/main/docker/mysql.yml b/jhipster-5/bookstore-monolith/src/main/docker/mysql.yml new file mode 100644 index 0000000000..13faba0457 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/docker/mysql.yml @@ -0,0 +1,13 @@ +version: '2' +services: + bookstore-mysql: + image: mysql:5.7.20 + # volumes: + # - ~/volumes/jhipster/Bookstore/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=bookstore + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp diff --git a/jhipster-5/bookstore-monolith/src/main/docker/sonar.yml b/jhipster-5/bookstore-monolith/src/main/docker/sonar.yml new file mode 100644 index 0000000000..756175b7d0 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/docker/sonar.yml @@ -0,0 +1,7 @@ +version: '2' +services: + bookstore-sonar: + image: sonarqube:7.1 + ports: + - 9001:9000 + - 9092:9092 diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/ApplicationWebXml.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/ApplicationWebXml.java new file mode 100644 index 0000000000..ca65727e77 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/ApplicationWebXml.java @@ -0,0 +1,21 @@ +package com.baeldung.jhipster5; + +import com.baeldung.jhipster5.config.DefaultProfileUtil; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +/** + * This is a helper Java class that provides an alternative to creating a web.xml. + * This will be invoked only when the application is deployed to a Servlet container like Tomcat, JBoss etc. + */ +public class ApplicationWebXml extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + /** + * set a default to use when no profile is configured. + */ + DefaultProfileUtil.addDefaultProfile(application.application()); + return application.sources(BookstoreApp.class); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/BookstoreApp.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/BookstoreApp.java new file mode 100644 index 0000000000..e7ca925228 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/BookstoreApp.java @@ -0,0 +1,98 @@ +package com.baeldung.jhipster5; + +import com.baeldung.jhipster5.config.ApplicationProperties; +import com.baeldung.jhipster5.config.DefaultProfileUtil; + +import io.github.jhipster.config.JHipsterConstants; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.core.env.Environment; + +import javax.annotation.PostConstruct; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Collection; + +@SpringBootApplication +@EnableConfigurationProperties({LiquibaseProperties.class, ApplicationProperties.class}) +public class BookstoreApp { + + private static final Logger log = LoggerFactory.getLogger(BookstoreApp.class); + + private final Environment env; + + public BookstoreApp(Environment env) { + this.env = env; + } + + /** + * Initializes Bookstore. + *

+ * Spring profiles can be configured with a program argument --spring.profiles.active=your-active-profile + *

+ * Properties are configured in the application.yml file. + * See {@link io.github.jhipster.config.JHipsterProperties} for a good example. + */ +@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false) +public class ApplicationProperties { + +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/AsyncConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/AsyncConfiguration.java new file mode 100644 index 0000000000..414fe152bf --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/AsyncConfiguration.java @@ -0,0 +1,59 @@ +package com.baeldung.jhipster5.config; + +import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor; +import io.github.jhipster.config.JHipsterProperties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.*; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +@Configuration +@EnableAsync +@EnableScheduling +public class AsyncConfiguration implements AsyncConfigurer, SchedulingConfigurer { + + private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class); + + private final JHipsterProperties jHipsterProperties; + + public AsyncConfiguration(JHipsterProperties jHipsterProperties) { + this.jHipsterProperties = jHipsterProperties; + } + + @Override + @Bean(name = "taskExecutor") + public Executor getAsyncExecutor() { + log.debug("Creating Async Task Executor"); + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize()); + executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize()); + executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity()); + executor.setThreadNamePrefix("bookstore-Executor-"); + return new ExceptionHandlingAsyncTaskExecutor(executor); + } + + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return new SimpleAsyncUncaughtExceptionHandler(); + } + + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + taskRegistrar.setScheduler(scheduledTaskExecutor()); + } + + @Bean + public Executor scheduledTaskExecutor() { + return Executors.newScheduledThreadPool(jHipsterProperties.getAsync().getCorePoolSize()); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/CloudDatabaseConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/CloudDatabaseConfiguration.java new file mode 100644 index 0000000000..887a1bae89 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/CloudDatabaseConfiguration.java @@ -0,0 +1,28 @@ +package com.baeldung.jhipster5.config; + +import io.github.jhipster.config.JHipsterConstants; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.config.java.AbstractCloudConfig; +import org.springframework.context.annotation.*; + +import javax.sql.DataSource; +import org.springframework.boot.context.properties.ConfigurationProperties; + + +@Configuration +@Profile(JHipsterConstants.SPRING_PROFILE_CLOUD) +public class CloudDatabaseConfiguration extends AbstractCloudConfig { + + private final Logger log = LoggerFactory.getLogger(CloudDatabaseConfiguration.class); + + private static final String CLOUD_CONFIGURATION_HIKARI_PREFIX = "spring.datasource.hikari"; + + @Bean + @ConfigurationProperties(CLOUD_CONFIGURATION_HIKARI_PREFIX) + public DataSource dataSource() { + log.info("Configuring JDBC datasource from a cloud provider"); + return connectionFactory().dataSource(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/Constants.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/Constants.java new file mode 100644 index 0000000000..dd8f717f98 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/Constants.java @@ -0,0 +1,17 @@ +package com.baeldung.jhipster5.config; + +/** + * Application constants. + */ +public final class Constants { + + // Regex for acceptable logins + public static final String LOGIN_REGEX = "^[_.@A-Za-z0-9-]*$"; + + public static final String SYSTEM_ACCOUNT = "system"; + public static final String ANONYMOUS_USER = "anonymoususer"; + public static final String DEFAULT_LANGUAGE = "en"; + + private Constants() { + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DatabaseConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DatabaseConfiguration.java new file mode 100644 index 0000000000..007b1d6431 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DatabaseConfiguration.java @@ -0,0 +1,59 @@ +package com.baeldung.jhipster5.config; + +import io.github.jhipster.config.JHipsterConstants; +import io.github.jhipster.config.h2.H2ConfigurationHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.sql.SQLException; + +@Configuration +@EnableJpaRepositories("com.baeldung.jhipster5.repository") +@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware") +@EnableTransactionManagement +public class DatabaseConfiguration { + + private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class); + + private final Environment env; + + public DatabaseConfiguration(Environment env) { + this.env = env; + } + + /** + * Open the TCP port for the H2 database, so it is available remotely. + * + * @return the H2 database TCP server + * @throws SQLException if the server failed to start + */ + @Bean(initMethod = "start", destroyMethod = "stop") + @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) + public Object h2TCPServer() throws SQLException { + String port = getValidPortForH2(); + log.debug("H2 database is available on port {}", port); + return H2ConfigurationHelper.createServer(port); + } + + private String getValidPortForH2() { + int port = Integer.parseInt(env.getProperty("server.port")); + if (port < 10000) { + port = 10000 + port; + } else { + if (port < 63536) { + port = port + 2000; + } else { + port = port - 2000; + } + } + return String.valueOf(port); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DateTimeFormatConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DateTimeFormatConfiguration.java new file mode 100644 index 0000000000..4415ce0b1e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DateTimeFormatConfiguration.java @@ -0,0 +1,20 @@ +package com.baeldung.jhipster5.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.format.FormatterRegistry; +import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * Configure the converters to use the ISO format for dates by default. + */ +@Configuration +public class DateTimeFormatConfiguration implements WebMvcConfigurer { + + @Override + public void addFormatters(FormatterRegistry registry) { + DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); + registrar.setUseIsoFormat(true); + registrar.registerFormatters(registry); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DefaultProfileUtil.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DefaultProfileUtil.java new file mode 100644 index 0000000000..2cfe16a1ae --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/DefaultProfileUtil.java @@ -0,0 +1,51 @@ +package com.baeldung.jhipster5.config; + +import io.github.jhipster.config.JHipsterConstants; + +import org.springframework.boot.SpringApplication; +import org.springframework.core.env.Environment; + +import java.util.*; + +/** + * Utility class to load a Spring profile to be used as default + * when there is no spring.profiles.active set in the environment or as command line argument. + * If the value is not available in application.yml then dev profile will be used as default. + */ +public final class DefaultProfileUtil { + + private static final String SPRING_PROFILE_DEFAULT = "spring.profiles.default"; + + private DefaultProfileUtil() { + } + + /** + * Set a default to use when no profile is configured. + * + * @param app the Spring application + */ + public static void addDefaultProfile(SpringApplication app) { + Map defProperties = new HashMap<>(); + /* + * The default profile to use when no other profiles are defined + * This cannot be set in the application.yml file. + * See https://github.com/spring-projects/spring-boot/issues/1219 + */ + defProperties.put(SPRING_PROFILE_DEFAULT, JHipsterConstants.SPRING_PROFILE_DEVELOPMENT); + app.setDefaultProperties(defProperties); + } + + /** + * Get the profiles that are applied else get default profiles. + * + * @param env spring environment + * @return profiles + */ + public static String[] getActiveProfiles(Environment env) { + String[] profiles = env.getActiveProfiles(); + if (profiles.length == 0) { + return env.getDefaultProfiles(); + } + return profiles; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/JacksonConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/JacksonConfiguration.java new file mode 100644 index 0000000000..119cd5f0c6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/JacksonConfiguration.java @@ -0,0 +1,63 @@ +package com.baeldung.jhipster5.config; + +import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.module.afterburner.AfterburnerModule; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.zalando.problem.ProblemModule; +import org.zalando.problem.violations.ConstraintViolationProblemModule; + +@Configuration +public class JacksonConfiguration { + + /** + * Support for Java date and time API. + * @return the corresponding Jackson module. + */ + @Bean + public JavaTimeModule javaTimeModule() { + return new JavaTimeModule(); + } + + @Bean + public Jdk8Module jdk8TimeModule() { + return new Jdk8Module(); + } + + + /* + * Support for Hibernate types in Jackson. + */ + @Bean + public Hibernate5Module hibernate5Module() { + return new Hibernate5Module(); + } + + /* + * Jackson Afterburner module to speed up serialization/deserialization. + */ + @Bean + public AfterburnerModule afterburnerModule() { + return new AfterburnerModule(); + } + + /* + * Module for serialization/deserialization of RFC7807 Problem. + */ + @Bean + ProblemModule problemModule() { + return new ProblemModule(); + } + + /* + * Module for serialization/deserialization of ConstraintViolationProblem. + */ + @Bean + ConstraintViolationProblemModule constraintViolationProblemModule() { + return new ConstraintViolationProblemModule(); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LiquibaseConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LiquibaseConfiguration.java new file mode 100644 index 0000000000..4b2a7b1e66 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LiquibaseConfiguration.java @@ -0,0 +1,50 @@ +package com.baeldung.jhipster5.config; + +import javax.sql.DataSource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.core.task.TaskExecutor; + +import io.github.jhipster.config.JHipsterConstants; +import io.github.jhipster.config.liquibase.AsyncSpringLiquibase; +import liquibase.integration.spring.SpringLiquibase; + +@Configuration +public class LiquibaseConfiguration { + + private final Logger log = LoggerFactory.getLogger(LiquibaseConfiguration.class); + + private final Environment env; + + + public LiquibaseConfiguration(Environment env) { + this.env = env; + } + + @Bean + public SpringLiquibase liquibase(@Qualifier("taskExecutor") TaskExecutor taskExecutor, + DataSource dataSource, LiquibaseProperties liquibaseProperties) { + + // Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously + SpringLiquibase liquibase = new AsyncSpringLiquibase(taskExecutor, env); + liquibase.setDataSource(dataSource); + liquibase.setChangeLog("classpath:config/liquibase/master.xml"); + liquibase.setContexts(liquibaseProperties.getContexts()); + liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema()); + liquibase.setDropFirst(liquibaseProperties.isDropFirst()); + liquibase.setChangeLogParameters(liquibaseProperties.getParameters()); + if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_NO_LIQUIBASE)) { + liquibase.setShouldRun(false); + } else { + liquibase.setShouldRun(liquibaseProperties.isEnabled()); + log.debug("Configuring Liquibase"); + } + return liquibase; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LocaleConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LocaleConfiguration.java new file mode 100644 index 0000000000..256c6b77b9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LocaleConfiguration.java @@ -0,0 +1,27 @@ +package com.baeldung.jhipster5.config; + +import io.github.jhipster.config.locale.AngularCookieLocaleResolver; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.config.annotation.*; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; + +@Configuration +public class LocaleConfiguration implements WebMvcConfigurer { + + @Bean(name = "localeResolver") + public LocaleResolver localeResolver() { + AngularCookieLocaleResolver cookieLocaleResolver = new AngularCookieLocaleResolver(); + cookieLocaleResolver.setCookieName("NG_TRANSLATE_LANG_KEY"); + return cookieLocaleResolver; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); + localeChangeInterceptor.setParamName("language"); + registry.addInterceptor(localeChangeInterceptor); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LoggingAspectConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LoggingAspectConfiguration.java new file mode 100644 index 0000000000..25d7ba3792 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LoggingAspectConfiguration.java @@ -0,0 +1,19 @@ +package com.baeldung.jhipster5.config; + +import com.baeldung.jhipster5.aop.logging.LoggingAspect; + +import io.github.jhipster.config.JHipsterConstants; + +import org.springframework.context.annotation.*; +import org.springframework.core.env.Environment; + +@Configuration +@EnableAspectJAutoProxy +public class LoggingAspectConfiguration { + + @Bean + @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) + public LoggingAspect loggingAspect(Environment env) { + return new LoggingAspect(env); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LoggingConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LoggingConfiguration.java new file mode 100644 index 0000000000..9402a1bc36 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/LoggingConfiguration.java @@ -0,0 +1,154 @@ +package com.baeldung.jhipster5.config; + +import java.net.InetSocketAddress; +import java.util.Iterator; + +import io.github.jhipster.config.JHipsterProperties; + +import ch.qos.logback.classic.AsyncAppender; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.boolex.OnMarkerEvaluator; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggerContextListener; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.filter.EvaluatorFilter; +import ch.qos.logback.core.spi.ContextAwareBase; +import ch.qos.logback.core.spi.FilterReply; +import net.logstash.logback.appender.LogstashTcpSocketAppender; +import net.logstash.logback.encoder.LogstashEncoder; +import net.logstash.logback.stacktrace.ShortenedThrowableConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class LoggingConfiguration { + + private static final String LOGSTASH_APPENDER_NAME = "LOGSTASH"; + + private static final String ASYNC_LOGSTASH_APPENDER_NAME = "ASYNC_LOGSTASH"; + + private final Logger log = LoggerFactory.getLogger(LoggingConfiguration.class); + + private LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + + private final String appName; + + private final String serverPort; + + private final JHipsterProperties jHipsterProperties; + + public LoggingConfiguration(@Value("${spring.application.name}") String appName, @Value("${server.port}") String serverPort, + JHipsterProperties jHipsterProperties) { + this.appName = appName; + this.serverPort = serverPort; + this.jHipsterProperties = jHipsterProperties; + if (jHipsterProperties.getLogging().getLogstash().isEnabled()) { + addLogstashAppender(context); + addContextListener(context); + } + if (jHipsterProperties.getMetrics().getLogs().isEnabled()) { + setMetricsMarkerLogbackFilter(context); + } + } + + private void addContextListener(LoggerContext context) { + LogbackLoggerContextListener loggerContextListener = new LogbackLoggerContextListener(); + loggerContextListener.setContext(context); + context.addListener(loggerContextListener); + } + + private void addLogstashAppender(LoggerContext context) { + log.info("Initializing Logstash logging"); + + LogstashTcpSocketAppender logstashAppender = new LogstashTcpSocketAppender(); + logstashAppender.setName(LOGSTASH_APPENDER_NAME); + logstashAppender.setContext(context); + String customFields = "{\"app_name\":\"" + appName + "\",\"app_port\":\"" + serverPort + "\"}"; + + // More documentation is available at: https://github.com/logstash/logstash-logback-encoder + LogstashEncoder logstashEncoder = new LogstashEncoder(); + // Set the Logstash appender config from JHipster properties + logstashAppender.addDestinations(new InetSocketAddress(jHipsterProperties.getLogging().getLogstash().getHost(), jHipsterProperties.getLogging().getLogstash().getPort())); + + ShortenedThrowableConverter throwableConverter = new ShortenedThrowableConverter(); + throwableConverter.setRootCauseFirst(true); + logstashEncoder.setThrowableConverter(throwableConverter); + logstashEncoder.setCustomFields(customFields); + + logstashAppender.setEncoder(logstashEncoder); + logstashAppender.start(); + + // Wrap the appender in an Async appender for performance + AsyncAppender asyncLogstashAppender = new AsyncAppender(); + asyncLogstashAppender.setContext(context); + asyncLogstashAppender.setName(ASYNC_LOGSTASH_APPENDER_NAME); + asyncLogstashAppender.setQueueSize(jHipsterProperties.getLogging().getLogstash().getQueueSize()); + asyncLogstashAppender.addAppender(logstashAppender); + asyncLogstashAppender.start(); + + context.getLogger("ROOT").addAppender(asyncLogstashAppender); + } + + // Configure a log filter to remove "metrics" logs from all appenders except the "LOGSTASH" appender + private void setMetricsMarkerLogbackFilter(LoggerContext context) { + log.info("Filtering metrics logs from all appenders except the {} appender", LOGSTASH_APPENDER_NAME); + OnMarkerEvaluator onMarkerMetricsEvaluator = new OnMarkerEvaluator(); + onMarkerMetricsEvaluator.setContext(context); + onMarkerMetricsEvaluator.addMarker("metrics"); + onMarkerMetricsEvaluator.start(); + EvaluatorFilter metricsFilter = new EvaluatorFilter<>(); + metricsFilter.setContext(context); + metricsFilter.setEvaluator(onMarkerMetricsEvaluator); + metricsFilter.setOnMatch(FilterReply.DENY); + metricsFilter.start(); + + for (ch.qos.logback.classic.Logger logger : context.getLoggerList()) { + for (Iterator> it = logger.iteratorForAppenders(); it.hasNext();) { + Appender appender = it.next(); + if (!appender.getName().equals(ASYNC_LOGSTASH_APPENDER_NAME)) { + log.debug("Filter metrics logs from the {} appender", appender.getName()); + appender.setContext(context); + appender.addFilter(metricsFilter); + appender.start(); + } + } + } + } + + /** + * Logback configuration is achieved by configuration file and API. + * When configuration file change is detected, the configuration is reset. + * This listener ensures that the programmatic configuration is also re-applied after reset. + */ + class LogbackLoggerContextListener extends ContextAwareBase implements LoggerContextListener { + + @Override + public boolean isResetResistant() { + return true; + } + + @Override + public void onStart(LoggerContext context) { + addLogstashAppender(context); + } + + @Override + public void onReset(LoggerContext context) { + addLogstashAppender(context); + } + + @Override + public void onStop(LoggerContext context) { + // Nothing to do. + } + + @Override + public void onLevelChange(ch.qos.logback.classic.Logger logger, Level level) { + // Nothing to do. + } + } + +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/SecurityConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/SecurityConfiguration.java new file mode 100644 index 0000000000..64111588f6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/SecurityConfiguration.java @@ -0,0 +1,121 @@ +package com.baeldung.jhipster5.config; + +import com.baeldung.jhipster5.security.*; +import com.baeldung.jhipster5.security.jwt.*; + +import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.filter.CorsFilter; +import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport; + +import javax.annotation.PostConstruct; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +@Import(SecurityProblemSupport.class) +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + private final AuthenticationManagerBuilder authenticationManagerBuilder; + + private final UserDetailsService userDetailsService; + + private final TokenProvider tokenProvider; + + private final CorsFilter corsFilter; + + private final SecurityProblemSupport problemSupport; + + public SecurityConfiguration(AuthenticationManagerBuilder authenticationManagerBuilder, UserDetailsService userDetailsService, TokenProvider tokenProvider, CorsFilter corsFilter, SecurityProblemSupport problemSupport) { + this.authenticationManagerBuilder = authenticationManagerBuilder; + this.userDetailsService = userDetailsService; + this.tokenProvider = tokenProvider; + this.corsFilter = corsFilter; + this.problemSupport = problemSupport; + } + + @PostConstruct + public void init() { + try { + authenticationManagerBuilder + .userDetailsService(userDetailsService) + .passwordEncoder(passwordEncoder()); + } catch (Exception e) { + throw new BeanInitializationException("Security configuration failed", e); + } + } + + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring() + .antMatchers(HttpMethod.OPTIONS, "/**") + .antMatchers("/app/**/*.{js,html}") + .antMatchers("/i18n/**") + .antMatchers("/content/**") + .antMatchers("/h2-console/**") + .antMatchers("/swagger-ui/index.html") + .antMatchers("/test/**"); + } + + @Override + public void configure(HttpSecurity http) throws Exception { + http + .csrf() + .disable() + .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class) + .exceptionHandling() + .authenticationEntryPoint(problemSupport) + .accessDeniedHandler(problemSupport) + .and() + .headers() + .frameOptions() + .disable() + .and() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .authorizeRequests() + .antMatchers("/api/register").permitAll() + .antMatchers("/api/activate").permitAll() + .antMatchers("/api/authenticate").permitAll() + .antMatchers("/api/account/reset-password/init").permitAll() + .antMatchers("/api/account/reset-password/finish").permitAll() + .antMatchers("/api/**").authenticated() + .antMatchers("/management/health").permitAll() + .antMatchers("/management/info").permitAll() + .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN) + .and() + .apply(securityConfigurerAdapter()); + + } + + private JWTConfigurer securityConfigurerAdapter() { + return new JWTConfigurer(tokenProvider); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/WebConfigurer.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/WebConfigurer.java new file mode 100644 index 0000000000..26cfc92487 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/WebConfigurer.java @@ -0,0 +1,170 @@ +package com.baeldung.jhipster5.config; + +import io.github.jhipster.config.JHipsterConstants; +import io.github.jhipster.config.JHipsterProperties; +import io.github.jhipster.config.h2.H2ConfigurationHelper; +import io.github.jhipster.web.filter.CachingHttpHeadersFilter; +import io.undertow.UndertowOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; +import org.springframework.boot.web.server.*; +import org.springframework.boot.web.servlet.ServletContextInitializer; +import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.http.MediaType; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +import javax.servlet.*; +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; +import java.util.*; + +import static java.net.URLDecoder.decode; + +/** + * Configuration of web application with Servlet 3.0 APIs. + */ +@Configuration +public class WebConfigurer implements ServletContextInitializer, WebServerFactoryCustomizer { + + private final Logger log = LoggerFactory.getLogger(WebConfigurer.class); + + private final Environment env; + + private final JHipsterProperties jHipsterProperties; + + public WebConfigurer(Environment env, JHipsterProperties jHipsterProperties) { + + this.env = env; + this.jHipsterProperties = jHipsterProperties; + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + if (env.getActiveProfiles().length != 0) { + log.info("Web application configuration, using profiles: {}", (Object[]) env.getActiveProfiles()); + } + EnumSet disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC); + if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) { + initCachingHttpHeadersFilter(servletContext, disps); + } + if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) { + initH2Console(servletContext); + } + log.info("Web application fully configured"); + } + + /** + * Customize the Servlet engine: Mime types, the document root, the cache. + */ + @Override + public void customize(WebServerFactory server) { + setMimeMappings(server); + // When running in an IDE or with ./mvnw spring-boot:run, set location of the static web assets. + setLocationForStaticAssets(server); + + /* + * Enable HTTP/2 for Undertow - https://twitter.com/ankinson/status/829256167700492288 + * HTTP/2 requires HTTPS, so HTTP requests will fallback to HTTP/1.1. + * See the JHipsterProperties class and your application-*.yml configuration files + * for more information. + */ + if (jHipsterProperties.getHttp().getVersion().equals(JHipsterProperties.Http.Version.V_2_0) && + server instanceof UndertowServletWebServerFactory) { + + ((UndertowServletWebServerFactory) server) + .addBuilderCustomizers(builder -> + builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true)); + } + } + + private void setMimeMappings(WebServerFactory server) { + if (server instanceof ConfigurableServletWebServerFactory) { + MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT); + // IE issue, see https://github.com/jhipster/generator-jhipster/pull/711 + mappings.add("html", MediaType.TEXT_HTML_VALUE + ";charset=" + StandardCharsets.UTF_8.name().toLowerCase()); + // CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64 + mappings.add("json", MediaType.TEXT_HTML_VALUE + ";charset=" + StandardCharsets.UTF_8.name().toLowerCase()); + ConfigurableServletWebServerFactory servletWebServer = (ConfigurableServletWebServerFactory) server; + servletWebServer.setMimeMappings(mappings); + } + } + + private void setLocationForStaticAssets(WebServerFactory server) { + if (server instanceof ConfigurableServletWebServerFactory) { + ConfigurableServletWebServerFactory servletWebServer = (ConfigurableServletWebServerFactory) server; + File root; + String prefixPath = resolvePathPrefix(); + root = new File(prefixPath + "target/www/"); + if (root.exists() && root.isDirectory()) { + servletWebServer.setDocumentRoot(root); + } + } + } + + /** + * Resolve path prefix to static resources. + */ + private String resolvePathPrefix() { + String fullExecutablePath; + try { + fullExecutablePath = decode(this.getClass().getResource("").getPath(), StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + /* try without decoding if this ever happens */ + fullExecutablePath = this.getClass().getResource("").getPath(); + } + String rootPath = Paths.get(".").toUri().normalize().getPath(); + String extractedPath = fullExecutablePath.replace(rootPath, ""); + int extractionEndIndex = extractedPath.indexOf("target/"); + if (extractionEndIndex <= 0) { + return ""; + } + return extractedPath.substring(0, extractionEndIndex); + } + + /** + * Initializes the caching HTTP Headers Filter. + */ + private void initCachingHttpHeadersFilter(ServletContext servletContext, + EnumSet disps) { + log.debug("Registering Caching HTTP Headers Filter"); + FilterRegistration.Dynamic cachingHttpHeadersFilter = + servletContext.addFilter("cachingHttpHeadersFilter", + new CachingHttpHeadersFilter(jHipsterProperties)); + + cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/i18n/*"); + cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/content/*"); + cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/app/*"); + cachingHttpHeadersFilter.setAsyncSupported(true); + } + + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + CorsConfiguration config = jHipsterProperties.getCors(); + if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) { + log.debug("Registering CORS filter"); + source.registerCorsConfiguration("/api/**", config); + source.registerCorsConfiguration("/management/**", config); + source.registerCorsConfiguration("/v2/api-docs", config); + } + return new CorsFilter(source); + } + + /** + * Initializes H2 console. + */ + private void initH2Console(ServletContext servletContext) { + log.debug("Initialize H2 console"); + H2ConfigurationHelper.initH2Console(servletContext); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/audit/AuditEventConverter.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/audit/AuditEventConverter.java new file mode 100644 index 0000000000..6dd87bb82d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/audit/AuditEventConverter.java @@ -0,0 +1,86 @@ +package com.baeldung.jhipster5.config.audit; + +import com.baeldung.jhipster5.domain.PersistentAuditEvent; + +import org.springframework.boot.actuate.audit.AuditEvent; +import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.stereotype.Component; + +import java.util.*; + +@Component +public class AuditEventConverter { + + /** + * Convert a list of PersistentAuditEvent to a list of AuditEvent + * + * @param persistentAuditEvents the list to convert + * @return the converted list. + */ + public List convertToAuditEvent(Iterable persistentAuditEvents) { + if (persistentAuditEvents == null) { + return Collections.emptyList(); + } + List auditEvents = new ArrayList<>(); + for (PersistentAuditEvent persistentAuditEvent : persistentAuditEvents) { + auditEvents.add(convertToAuditEvent(persistentAuditEvent)); + } + return auditEvents; + } + + /** + * Convert a PersistentAuditEvent to an AuditEvent + * + * @param persistentAuditEvent the event to convert + * @return the converted list. + */ + public AuditEvent convertToAuditEvent(PersistentAuditEvent persistentAuditEvent) { + if (persistentAuditEvent == null) { + return null; + } + return new AuditEvent(persistentAuditEvent.getAuditEventDate(), persistentAuditEvent.getPrincipal(), + persistentAuditEvent.getAuditEventType(), convertDataToObjects(persistentAuditEvent.getData())); + } + + /** + * Internal conversion. This is needed to support the current SpringBoot actuator AuditEventRepository interface + * + * @param data the data to convert + * @return a map of String, Object + */ + public Map convertDataToObjects(Map data) { + Map results = new HashMap<>(); + + if (data != null) { + for (Map.Entry entry : data.entrySet()) { + results.put(entry.getKey(), entry.getValue()); + } + } + return results; + } + + /** + * Internal conversion. This method will allow to save additional data. + * By default, it will save the object as string + * + * @param data the data to convert + * @return a map of String, String + */ + public Map convertDataToStrings(Map data) { + Map results = new HashMap<>(); + + if (data != null) { + for (Map.Entry entry : data.entrySet()) { + // Extract the data that will be saved. + if (entry.getValue() instanceof WebAuthenticationDetails) { + WebAuthenticationDetails authenticationDetails = (WebAuthenticationDetails) entry.getValue(); + results.put("remoteAddress", authenticationDetails.getRemoteAddress()); + results.put("sessionId", authenticationDetails.getSessionId()); + } else { + results.put(entry.getKey(), Objects.toString(entry.getValue())); + } + } + } + return results; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/audit/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/audit/package-info.java new file mode 100644 index 0000000000..49a2a73a61 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/audit/package-info.java @@ -0,0 +1,4 @@ +/** + * Audit specific code. + */ +package com.baeldung.jhipster5.config.audit; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/package-info.java new file mode 100644 index 0000000000..868155ce9f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/package-info.java @@ -0,0 +1,4 @@ +/** + * Spring Framework configuration files. + */ +package com.baeldung.jhipster5.config; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/AbstractAuditingEntity.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/AbstractAuditingEntity.java new file mode 100644 index 0000000000..861674ccc9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/AbstractAuditingEntity.java @@ -0,0 +1,79 @@ +package com.baeldung.jhipster5.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.hibernate.envers.Audited; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.io.Serializable; +import java.time.Instant; +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; + +/** + * Base abstract class for entities which will hold definitions for created, last modified by and created, + * last modified by date. + */ +@MappedSuperclass +@Audited +@EntityListeners(AuditingEntityListener.class) +public abstract class AbstractAuditingEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @CreatedBy + @Column(name = "created_by", nullable = false, length = 50, updatable = false) + @JsonIgnore + private String createdBy; + + @CreatedDate + @Column(name = "created_date", updatable = false) + @JsonIgnore + private Instant createdDate = Instant.now(); + + @LastModifiedBy + @Column(name = "last_modified_by", length = 50) + @JsonIgnore + private String lastModifiedBy; + + @LastModifiedDate + @Column(name = "last_modified_date") + @JsonIgnore + private Instant lastModifiedDate = Instant.now(); + + public String getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public Instant getCreatedDate() { + return createdDate; + } + + public void setCreatedDate(Instant createdDate) { + this.createdDate = createdDate; + } + + public String getLastModifiedBy() { + return lastModifiedBy; + } + + public void setLastModifiedBy(String lastModifiedBy) { + this.lastModifiedBy = lastModifiedBy; + } + + public Instant getLastModifiedDate() { + return lastModifiedDate; + } + + public void setLastModifiedDate(Instant lastModifiedDate) { + this.lastModifiedDate = lastModifiedDate; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/Authority.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/Authority.java new file mode 100644 index 0000000000..fbd4596fc7 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/Authority.java @@ -0,0 +1,59 @@ +package com.baeldung.jhipster5.domain; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Column; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.io.Serializable; + +/** + * An authority (a security role) used by Spring Security. + */ +@Entity +@Table(name = "jhi_authority") +public class Authority implements Serializable { + + private static final long serialVersionUID = 1L; + + @NotNull + @Size(max = 50) + @Id + @Column(length = 50) + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Authority authority = (Authority) o; + + return !(name != null ? !name.equals(authority.name) : authority.name != null); + } + + @Override + public int hashCode() { + return name != null ? name.hashCode() : 0; + } + + @Override + public String toString() { + return "Authority{" + + "name='" + name + '\'' + + "}"; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/PersistentAuditEvent.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/PersistentAuditEvent.java new file mode 100644 index 0000000000..15e2eeda5a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/PersistentAuditEvent.java @@ -0,0 +1,109 @@ +package com.baeldung.jhipster5.domain; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.time.Instant; +import java.util.HashMap; +import java.util.Objects; +import java.util.Map; + +/** + * Persist AuditEvent managed by the Spring Boot actuator. + * + * @see org.springframework.boot.actuate.audit.AuditEvent + */ +@Entity +@Table(name = "jhi_persistent_audit_event") +public class PersistentAuditEvent implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "event_id") + private Long id; + + @NotNull + @Column(nullable = false) + private String principal; + + @Column(name = "event_date") + private Instant auditEventDate; + + @Column(name = "event_type") + private String auditEventType; + + @ElementCollection + @MapKeyColumn(name = "name") + @Column(name = "value") + @CollectionTable(name = "jhi_persistent_audit_evt_data", joinColumns=@JoinColumn(name="event_id")) + private Map data = new HashMap<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getPrincipal() { + return principal; + } + + public void setPrincipal(String principal) { + this.principal = principal; + } + + public Instant getAuditEventDate() { + return auditEventDate; + } + + public void setAuditEventDate(Instant auditEventDate) { + this.auditEventDate = auditEventDate; + } + + public String getAuditEventType() { + return auditEventType; + } + + public void setAuditEventType(String auditEventType) { + this.auditEventType = auditEventType; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + PersistentAuditEvent persistentAuditEvent = (PersistentAuditEvent) o; + return !(persistentAuditEvent.getId() == null || getId() == null) && Objects.equals(getId(), persistentAuditEvent.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(getId()); + } + + @Override + public String toString() { + return "PersistentAuditEvent{" + + "principal='" + principal + '\'' + + ", auditEventDate=" + auditEventDate + + ", auditEventType='" + auditEventType + '\'' + + '}'; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/User.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/User.java new file mode 100644 index 0000000000..ff12d1ca9c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/User.java @@ -0,0 +1,231 @@ +package com.baeldung.jhipster5.domain; + +import com.baeldung.jhipster5.config.Constants; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.annotations.BatchSize; +import javax.validation.constraints.Email; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Locale; +import java.util.Objects; +import java.util.Set; +import java.time.Instant; + +/** + * A user. + */ +@Entity +@Table(name = "jhi_user") + +public class User extends AbstractAuditingEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @Pattern(regexp = Constants.LOGIN_REGEX) + @Size(min = 1, max = 50) + @Column(length = 50, unique = true, nullable = false) + private String login; + + @JsonIgnore + @NotNull + @Size(min = 60, max = 60) + @Column(name = "password_hash", length = 60, nullable = false) + private String password; + + @Size(max = 50) + @Column(name = "first_name", length = 50) + private String firstName; + + @Size(max = 50) + @Column(name = "last_name", length = 50) + private String lastName; + + @Email + @Size(min = 5, max = 254) + @Column(length = 254, unique = true) + private String email; + + @NotNull + @Column(nullable = false) + private boolean activated = false; + + @Size(min = 2, max = 6) + @Column(name = "lang_key", length = 6) + private String langKey; + + @Size(max = 256) + @Column(name = "image_url", length = 256) + private String imageUrl; + + @Size(max = 20) + @Column(name = "activation_key", length = 20) + @JsonIgnore + private String activationKey; + + @Size(max = 20) + @Column(name = "reset_key", length = 20) + @JsonIgnore + private String resetKey; + + @Column(name = "reset_date") + private Instant resetDate = null; + + @JsonIgnore + @ManyToMany + @JoinTable( + name = "jhi_user_authority", + joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, + inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "name")}) + + @BatchSize(size = 20) + private Set authorities = new HashSet<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getLogin() { + return login; + } + + // Lowercase the login before saving it in database + public void setLogin(String login) { + this.login = StringUtils.lowerCase(login, Locale.ENGLISH); + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + public boolean getActivated() { + return activated; + } + + public void setActivated(boolean activated) { + this.activated = activated; + } + + public String getActivationKey() { + return activationKey; + } + + public void setActivationKey(String activationKey) { + this.activationKey = activationKey; + } + + public String getResetKey() { + return resetKey; + } + + public void setResetKey(String resetKey) { + this.resetKey = resetKey; + } + + public Instant getResetDate() { + return resetDate; + } + + public void setResetDate(Instant resetDate) { + this.resetDate = resetDate; + } + + public String getLangKey() { + return langKey; + } + + public void setLangKey(String langKey) { + this.langKey = langKey; + } + + public Set getAuthorities() { + return authorities; + } + + public void setAuthorities(Set authorities) { + this.authorities = authorities; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + User user = (User) o; + return !(user.getId() == null || getId() == null) && Objects.equals(getId(), user.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(getId()); + } + + @Override + public String toString() { + return "User{" + + "login='" + login + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", email='" + email + '\'' + + ", imageUrl='" + imageUrl + '\'' + + ", activated='" + activated + '\'' + + ", langKey='" + langKey + '\'' + + ", activationKey='" + activationKey + '\'' + + "}"; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/package-info.java new file mode 100644 index 0000000000..eba92a598e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/package-info.java @@ -0,0 +1,4 @@ +/** + * JPA domain objects. + */ +package com.baeldung.jhipster5.domain; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/AuthorityRepository.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/AuthorityRepository.java new file mode 100644 index 0000000000..310735eb57 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/AuthorityRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.jhipster5.repository; + +import com.baeldung.jhipster5.domain.Authority; + +import org.springframework.data.jpa.repository.JpaRepository; + +/** + * Spring Data JPA repository for the Authority entity. + */ +public interface AuthorityRepository extends JpaRepository { +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/CustomAuditEventRepository.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/CustomAuditEventRepository.java new file mode 100644 index 0000000000..faa788ff5f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/CustomAuditEventRepository.java @@ -0,0 +1,89 @@ +package com.baeldung.jhipster5.repository; + +import com.baeldung.jhipster5.config.Constants; +import com.baeldung.jhipster5.config.audit.AuditEventConverter; +import com.baeldung.jhipster5.domain.PersistentAuditEvent; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.actuate.audit.AuditEvent; +import org.springframework.boot.actuate.audit.AuditEventRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Instant; +import java.util.*; + +/** + * An implementation of Spring Boot's AuditEventRepository. + */ +@Repository +public class CustomAuditEventRepository implements AuditEventRepository { + + private static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE"; + + /** + * Should be the same as in Liquibase migration. + */ + protected static final int EVENT_DATA_COLUMN_MAX_LENGTH = 255; + + private final PersistenceAuditEventRepository persistenceAuditEventRepository; + + private final AuditEventConverter auditEventConverter; + + private final Logger log = LoggerFactory.getLogger(getClass()); + + public CustomAuditEventRepository(PersistenceAuditEventRepository persistenceAuditEventRepository, + AuditEventConverter auditEventConverter) { + + this.persistenceAuditEventRepository = persistenceAuditEventRepository; + this.auditEventConverter = auditEventConverter; + } + + @Override + public List find(String principal, Instant after, String type) { + Iterable persistentAuditEvents = + persistenceAuditEventRepository.findByPrincipalAndAuditEventDateAfterAndAuditEventType(principal, after, type); + return auditEventConverter.convertToAuditEvent(persistentAuditEvents); + } + + @Override + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void add(AuditEvent event) { + if (!AUTHORIZATION_FAILURE.equals(event.getType()) && + !Constants.ANONYMOUS_USER.equals(event.getPrincipal())) { + + PersistentAuditEvent persistentAuditEvent = new PersistentAuditEvent(); + persistentAuditEvent.setPrincipal(event.getPrincipal()); + persistentAuditEvent.setAuditEventType(event.getType()); + persistentAuditEvent.setAuditEventDate(event.getTimestamp()); + Map eventData = auditEventConverter.convertDataToStrings(event.getData()); + persistentAuditEvent.setData(truncate(eventData)); + persistenceAuditEventRepository.save(persistentAuditEvent); + } + } + + /** + * Truncate event data that might exceed column length. + */ + private Map truncate(Map data) { + Map results = new HashMap<>(); + + if (data != null) { + for (Map.Entry entry : data.entrySet()) { + String value = entry.getValue(); + if (value != null) { + int length = value.length(); + if (length > EVENT_DATA_COLUMN_MAX_LENGTH) { + value = value.substring(0, EVENT_DATA_COLUMN_MAX_LENGTH); + log.warn("Event data for {} too long ({}) has been truncated to {}. Consider increasing column width.", + entry.getKey(), length, EVENT_DATA_COLUMN_MAX_LENGTH); + } + } + results.put(entry.getKey(), value); + } + } + return results; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/PersistenceAuditEventRepository.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/PersistenceAuditEventRepository.java new file mode 100644 index 0000000000..2eb6f3b847 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/PersistenceAuditEventRepository.java @@ -0,0 +1,25 @@ +package com.baeldung.jhipster5.repository; + +import com.baeldung.jhipster5.domain.PersistentAuditEvent; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.time.Instant; +import java.util.List; + +/** + * Spring Data JPA repository for the PersistentAuditEvent entity. + */ +public interface PersistenceAuditEventRepository extends JpaRepository { + + List findByPrincipal(String principal); + + List findByAuditEventDateAfter(Instant after); + + List findByPrincipalAndAuditEventDateAfter(String principal, Instant after); + + List findByPrincipalAndAuditEventDateAfterAndAuditEventType(String principal, Instant after, String type); + + Page findAllByAuditEventDateBetween(Instant fromDate, Instant toDate, Pageable pageable); +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/UserRepository.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/UserRepository.java new file mode 100644 index 0000000000..42a5588b22 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/UserRepository.java @@ -0,0 +1,40 @@ +package com.baeldung.jhipster5.repository; + +import com.baeldung.jhipster5.domain.User; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Optional; +import java.time.Instant; + +/** + * Spring Data JPA repository for the User entity. + */ +@Repository +public interface UserRepository extends JpaRepository { + + Optional findOneByActivationKey(String activationKey); + + List findAllByActivatedIsFalseAndCreatedDateBefore(Instant dateTime); + + Optional findOneByResetKey(String resetKey); + + Optional findOneByEmailIgnoreCase(String email); + + Optional findOneByLogin(String login); + + @EntityGraph(attributePaths = "authorities") + Optional findOneWithAuthoritiesById(Long id); + + @EntityGraph(attributePaths = "authorities") + Optional findOneWithAuthoritiesByLogin(String login); + + @EntityGraph(attributePaths = "authorities") + Optional findOneWithAuthoritiesByEmail(String email); + + Page findAllByLoginNot(Pageable pageable, String login); +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/package-info.java new file mode 100644 index 0000000000..a5002eb201 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/package-info.java @@ -0,0 +1,4 @@ +/** + * Spring Data JPA repositories. + */ +package com.baeldung.jhipster5.repository; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/AuthoritiesConstants.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/AuthoritiesConstants.java new file mode 100644 index 0000000000..6ecf44394f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/AuthoritiesConstants.java @@ -0,0 +1,16 @@ +package com.baeldung.jhipster5.security; + +/** + * Constants for Spring Security authorities. + */ +public final class AuthoritiesConstants { + + public static final String ADMIN = "ROLE_ADMIN"; + + public static final String USER = "ROLE_USER"; + + public static final String ANONYMOUS = "ROLE_ANONYMOUS"; + + private AuthoritiesConstants() { + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/DomainUserDetailsService.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/DomainUserDetailsService.java new file mode 100644 index 0000000000..d0014096df --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/DomainUserDetailsService.java @@ -0,0 +1,62 @@ +package com.baeldung.jhipster5.security; + +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.repository.UserRepository; +import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Authenticate a user from the database. + */ +@Component("userDetailsService") +public class DomainUserDetailsService implements UserDetailsService { + + private final Logger log = LoggerFactory.getLogger(DomainUserDetailsService.class); + + private final UserRepository userRepository; + + public DomainUserDetailsService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + @Transactional + public UserDetails loadUserByUsername(final String login) { + log.debug("Authenticating {}", login); + + if (new EmailValidator().isValid(login, null)) { + return userRepository.findOneWithAuthoritiesByEmail(login) + .map(user -> createSpringSecurityUser(login, user)) + .orElseThrow(() -> new UsernameNotFoundException("User with email " + login + " was not found in the database")); + } + + String lowercaseLogin = login.toLowerCase(Locale.ENGLISH); + return userRepository.findOneWithAuthoritiesByLogin(lowercaseLogin) + .map(user -> createSpringSecurityUser(lowercaseLogin, user)) + .orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the database")); + + } + + private org.springframework.security.core.userdetails.User createSpringSecurityUser(String lowercaseLogin, User user) { + if (!user.getActivated()) { + throw new UserNotActivatedException("User " + lowercaseLogin + " was not activated"); + } + List grantedAuthorities = user.getAuthorities().stream() + .map(authority -> new SimpleGrantedAuthority(authority.getName())) + .collect(Collectors.toList()); + return new org.springframework.security.core.userdetails.User(user.getLogin(), + user.getPassword(), + grantedAuthorities); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/SecurityUtils.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/SecurityUtils.java new file mode 100644 index 0000000000..462bb8abc9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/SecurityUtils.java @@ -0,0 +1,76 @@ +package com.baeldung.jhipster5.security; + +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Optional; + +/** + * Utility class for Spring Security. + */ +public final class SecurityUtils { + + private SecurityUtils() { + } + + /** + * Get the login of the current user. + * + * @return the login of the current user + */ + public static Optional getCurrentUserLogin() { + SecurityContext securityContext = SecurityContextHolder.getContext(); + return Optional.ofNullable(securityContext.getAuthentication()) + .map(authentication -> { + if (authentication.getPrincipal() instanceof UserDetails) { + UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal(); + return springSecurityUser.getUsername(); + } else if (authentication.getPrincipal() instanceof String) { + return (String) authentication.getPrincipal(); + } + return null; + }); + } + + /** + * Get the JWT of the current user. + * + * @return the JWT of the current user + */ + public static Optional getCurrentUserJWT() { + SecurityContext securityContext = SecurityContextHolder.getContext(); + return Optional.ofNullable(securityContext.getAuthentication()) + .filter(authentication -> authentication.getCredentials() instanceof String) + .map(authentication -> (String) authentication.getCredentials()); + } + + /** + * Check if a user is authenticated. + * + * @return true if the user is authenticated, false otherwise + */ + public static boolean isAuthenticated() { + SecurityContext securityContext = SecurityContextHolder.getContext(); + return Optional.ofNullable(securityContext.getAuthentication()) + .map(authentication -> authentication.getAuthorities().stream() + .noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(AuthoritiesConstants.ANONYMOUS))) + .orElse(false); + } + + /** + * If the current user has a specific authority (security role). + *

+ * The name of this method comes from the isUserInRole() method in the Servlet API + * + * @param authority the authority to check + * @return true if the current user has the authority, false otherwise + */ + public static boolean isCurrentUserInRole(String authority) { + SecurityContext securityContext = SecurityContextHolder.getContext(); + return Optional.ofNullable(securityContext.getAuthentication()) + .map(authentication -> authentication.getAuthorities().stream() + .anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority))) + .orElse(false); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/SpringSecurityAuditorAware.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/SpringSecurityAuditorAware.java new file mode 100644 index 0000000000..c1d6405ae3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/SpringSecurityAuditorAware.java @@ -0,0 +1,20 @@ +package com.baeldung.jhipster5.security; + +import com.baeldung.jhipster5.config.Constants; + +import java.util.Optional; + +import org.springframework.data.domain.AuditorAware; +import org.springframework.stereotype.Component; + +/** + * Implementation of AuditorAware based on Spring Security. + */ +@Component +public class SpringSecurityAuditorAware implements AuditorAware { + + @Override + public Optional getCurrentAuditor() { + return Optional.of(SecurityUtils.getCurrentUserLogin().orElse(Constants.SYSTEM_ACCOUNT)); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/UserNotActivatedException.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/UserNotActivatedException.java new file mode 100644 index 0000000000..4b2d91983c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/UserNotActivatedException.java @@ -0,0 +1,19 @@ +package com.baeldung.jhipster5.security; + +import org.springframework.security.core.AuthenticationException; + +/** + * This exception is thrown in case of a not activated user trying to authenticate. + */ +public class UserNotActivatedException extends AuthenticationException { + + private static final long serialVersionUID = 1L; + + public UserNotActivatedException(String message) { + super(message); + } + + public UserNotActivatedException(String message, Throwable t) { + super(message, t); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/JWTConfigurer.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/JWTConfigurer.java new file mode 100644 index 0000000000..944255e37d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/JWTConfigurer.java @@ -0,0 +1,21 @@ +package com.baeldung.jhipster5.security.jwt; + +import org.springframework.security.config.annotation.SecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.DefaultSecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +public class JWTConfigurer extends SecurityConfigurerAdapter { + + private TokenProvider tokenProvider; + + public JWTConfigurer(TokenProvider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public void configure(HttpSecurity http) throws Exception { + JWTFilter customFilter = new JWTFilter(tokenProvider); + http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/JWTFilter.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/JWTFilter.java new file mode 100644 index 0000000000..cf1060282c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/JWTFilter.java @@ -0,0 +1,48 @@ +package com.baeldung.jhipster5.security.jwt; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.GenericFilterBean; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * Filters incoming requests and installs a Spring Security principal if a header corresponding to a valid user is + * found. + */ +public class JWTFilter extends GenericFilterBean { + + public static final String AUTHORIZATION_HEADER = "Authorization"; + + private TokenProvider tokenProvider; + + public JWTFilter(TokenProvider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; + String jwt = resolveToken(httpServletRequest); + if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) { + Authentication authentication = this.tokenProvider.getAuthentication(jwt); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + filterChain.doFilter(servletRequest, servletResponse); + } + + private String resolveToken(HttpServletRequest request){ + String bearerToken = request.getHeader(AUTHORIZATION_HEADER); + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { + return bearerToken.substring(7); + } + return null; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/TokenProvider.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/TokenProvider.java new file mode 100644 index 0000000000..248d45e050 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/jwt/TokenProvider.java @@ -0,0 +1,119 @@ +package com.baeldung.jhipster5.security.jwt; + +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.util.*; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import io.github.jhipster.config.JHipsterProperties; +import io.jsonwebtoken.*; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.security.Keys; + +@Component +public class TokenProvider { + + private final Logger log = LoggerFactory.getLogger(TokenProvider.class); + + private static final String AUTHORITIES_KEY = "auth"; + + private Key key; + + private long tokenValidityInMilliseconds; + + private long tokenValidityInMillisecondsForRememberMe; + + private final JHipsterProperties jHipsterProperties; + + public TokenProvider(JHipsterProperties jHipsterProperties) { + this.jHipsterProperties = jHipsterProperties; + } + + @PostConstruct + public void init() { + byte[] keyBytes; + String secret = jHipsterProperties.getSecurity().getAuthentication().getJwt().getSecret(); + if (!StringUtils.isEmpty(secret)) { + log.warn("Warning: the JWT key used is not Base64-encoded. " + + "We recommend using the `jhipster.security.authentication.jwt.base64-secret` key for optimum security."); + keyBytes = secret.getBytes(StandardCharsets.UTF_8); + } else { + log.debug("Using a Base64-encoded JWT secret key"); + keyBytes = Decoders.BASE64.decode(jHipsterProperties.getSecurity().getAuthentication().getJwt().getBase64Secret()); + } + this.key = Keys.hmacShaKeyFor(keyBytes); + this.tokenValidityInMilliseconds = + 1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt().getTokenValidityInSeconds(); + this.tokenValidityInMillisecondsForRememberMe = + 1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt() + .getTokenValidityInSecondsForRememberMe(); + } + + public String createToken(Authentication authentication, boolean rememberMe) { + String authorities = authentication.getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .collect(Collectors.joining(",")); + + long now = (new Date()).getTime(); + Date validity; + if (rememberMe) { + validity = new Date(now + this.tokenValidityInMillisecondsForRememberMe); + } else { + validity = new Date(now + this.tokenValidityInMilliseconds); + } + + return Jwts.builder() + .setSubject(authentication.getName()) + .claim(AUTHORITIES_KEY, authorities) + .signWith(key, SignatureAlgorithm.HS512) + .setExpiration(validity) + .compact(); + } + + public Authentication getAuthentication(String token) { + Claims claims = Jwts.parser() + .setSigningKey(key) + .parseClaimsJws(token) + .getBody(); + + Collection authorities = + Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) + .map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + + User principal = new User(claims.getSubject(), "", authorities); + + return new UsernamePasswordAuthenticationToken(principal, token, authorities); + } + + public boolean validateToken(String authToken) { + try { + Jwts.parser().setSigningKey(key).parseClaimsJws(authToken); + return true; + } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { + log.info("Invalid JWT signature."); + log.trace("Invalid JWT signature trace: {}", e); + } catch (ExpiredJwtException e) { + log.info("Expired JWT token."); + log.trace("Expired JWT token trace: {}", e); + } catch (UnsupportedJwtException e) { + log.info("Unsupported JWT token."); + log.trace("Unsupported JWT token trace: {}", e); + } catch (IllegalArgumentException e) { + log.info("JWT token compact of handler are invalid."); + log.trace("JWT token compact of handler are invalid trace: {}", e); + } + return false; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/package-info.java new file mode 100644 index 0000000000..4759050c56 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/security/package-info.java @@ -0,0 +1,4 @@ +/** + * Spring Security configuration. + */ +package com.baeldung.jhipster5.security; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/AuditEventService.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/AuditEventService.java new file mode 100644 index 0000000000..852eb951c9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/AuditEventService.java @@ -0,0 +1,51 @@ +package com.baeldung.jhipster5.service; + +import com.baeldung.jhipster5.config.audit.AuditEventConverter; +import com.baeldung.jhipster5.repository.PersistenceAuditEventRepository; +import org.springframework.boot.actuate.audit.AuditEvent; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Instant; +import java.util.Optional; + +/** + * Service for managing audit events. + *

+ * This is the default implementation to support SpringBoot Actuator AuditEventRepository + */ +@Service +@Transactional +public class AuditEventService { + + private final PersistenceAuditEventRepository persistenceAuditEventRepository; + + private final AuditEventConverter auditEventConverter; + + public AuditEventService( + PersistenceAuditEventRepository persistenceAuditEventRepository, + AuditEventConverter auditEventConverter) { + + this.persistenceAuditEventRepository = persistenceAuditEventRepository; + this.auditEventConverter = auditEventConverter; + } + + public Page findAll(Pageable pageable) { + return persistenceAuditEventRepository.findAll(pageable) + .map(auditEventConverter::convertToAuditEvent); + } + + public Page findByDates(Instant fromDate, Instant toDate, Pageable pageable) { + return persistenceAuditEventRepository.findAllByAuditEventDateBetween(fromDate, toDate, pageable) + .map(auditEventConverter::convertToAuditEvent); + } + + public Optional find(Long id) { + return Optional.ofNullable(persistenceAuditEventRepository.findById(id)) + .filter(Optional::isPresent) + .map(Optional::get) + .map(auditEventConverter::convertToAuditEvent); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/MailService.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/MailService.java new file mode 100644 index 0000000000..b15a7faff2 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/MailService.java @@ -0,0 +1,105 @@ +package com.baeldung.jhipster5.service; + +import com.baeldung.jhipster5.domain.User; + +import io.github.jhipster.config.JHipsterProperties; + +import java.nio.charset.StandardCharsets; +import java.util.Locale; +import javax.mail.internet.MimeMessage; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.MessageSource; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.thymeleaf.context.Context; +import org.thymeleaf.spring5.SpringTemplateEngine; + +/** + * Service for sending emails. + *

+ * We use the @Async annotation to send emails asynchronously. + */ +@Service +public class MailService { + + private final Logger log = LoggerFactory.getLogger(MailService.class); + + private static final String USER = "user"; + + private static final String BASE_URL = "baseUrl"; + + private final JHipsterProperties jHipsterProperties; + + private final JavaMailSender javaMailSender; + + private final MessageSource messageSource; + + private final SpringTemplateEngine templateEngine; + + public MailService(JHipsterProperties jHipsterProperties, JavaMailSender javaMailSender, + MessageSource messageSource, SpringTemplateEngine templateEngine) { + + this.jHipsterProperties = jHipsterProperties; + this.javaMailSender = javaMailSender; + this.messageSource = messageSource; + this.templateEngine = templateEngine; + } + + @Async + public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) { + log.debug("Send email[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}", + isMultipart, isHtml, to, subject, content); + + // Prepare message using a Spring helper + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + try { + MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, StandardCharsets.UTF_8.name()); + message.setTo(to); + message.setFrom(jHipsterProperties.getMail().getFrom()); + message.setSubject(subject); + message.setText(content, isHtml); + javaMailSender.send(mimeMessage); + log.debug("Sent email to User '{}'", to); + } catch (Exception e) { + if (log.isDebugEnabled()) { + log.warn("Email could not be sent to user '{}'", to, e); + } else { + log.warn("Email could not be sent to user '{}': {}", to, e.getMessage()); + } + } + } + + @Async + public void sendEmailFromTemplate(User user, String templateName, String titleKey) { + Locale locale = Locale.forLanguageTag(user.getLangKey()); + Context context = new Context(locale); + context.setVariable(USER, user); + context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl()); + String content = templateEngine.process(templateName, context); + String subject = messageSource.getMessage(titleKey, null, locale); + sendEmail(user.getEmail(), subject, content, false, true); + + } + + @Async + public void sendActivationEmail(User user) { + log.debug("Sending activation email to '{}'", user.getEmail()); + sendEmailFromTemplate(user, "mail/activationEmail", "email.activation.title"); + } + + @Async + public void sendCreationEmail(User user) { + log.debug("Sending creation email to '{}'", user.getEmail()); + sendEmailFromTemplate(user, "mail/creationEmail", "email.activation.title"); + } + + @Async + public void sendPasswordResetMail(User user) { + log.debug("Sending password reset email to '{}'", user.getEmail()); + sendEmailFromTemplate(user, "mail/passwordResetEmail", "email.reset.title"); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/UserService.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/UserService.java new file mode 100644 index 0000000000..82d028f3ca --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/UserService.java @@ -0,0 +1,273 @@ +package com.baeldung.jhipster5.service; + +import com.baeldung.jhipster5.config.Constants; +import com.baeldung.jhipster5.domain.Authority; +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.repository.AuthorityRepository; +import com.baeldung.jhipster5.repository.UserRepository; +import com.baeldung.jhipster5.security.AuthoritiesConstants; +import com.baeldung.jhipster5.security.SecurityUtils; +import com.baeldung.jhipster5.service.dto.UserDTO; +import com.baeldung.jhipster5.service.util.RandomUtil; +import com.baeldung.jhipster5.web.rest.errors.*; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Service class for managing users. + */ +@Service +@Transactional +public class UserService { + + private final Logger log = LoggerFactory.getLogger(UserService.class); + + private final UserRepository userRepository; + + private final PasswordEncoder passwordEncoder; + + private final AuthorityRepository authorityRepository; + + public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, AuthorityRepository authorityRepository) { + this.userRepository = userRepository; + this.passwordEncoder = passwordEncoder; + this.authorityRepository = authorityRepository; + } + + public Optional activateRegistration(String key) { + log.debug("Activating user for activation key {}", key); + return userRepository.findOneByActivationKey(key) + .map(user -> { + // activate given user for the registration key. + user.setActivated(true); + user.setActivationKey(null); + log.debug("Activated user: {}", user); + return user; + }); + } + + public Optional completePasswordReset(String newPassword, String key) { + log.debug("Reset user password for reset key {}", key); + return userRepository.findOneByResetKey(key) + .filter(user -> user.getResetDate().isAfter(Instant.now().minusSeconds(86400))) + .map(user -> { + user.setPassword(passwordEncoder.encode(newPassword)); + user.setResetKey(null); + user.setResetDate(null); + return user; + }); + } + + public Optional requestPasswordReset(String mail) { + return userRepository.findOneByEmailIgnoreCase(mail) + .filter(User::getActivated) + .map(user -> { + user.setResetKey(RandomUtil.generateResetKey()); + user.setResetDate(Instant.now()); + return user; + }); + } + + public User registerUser(UserDTO userDTO, String password) { + userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()).ifPresent(existingUser -> { + boolean removed = removeNonActivatedUser(existingUser); + if (!removed) { + throw new LoginAlreadyUsedException(); + } + }); + userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()).ifPresent(existingUser -> { + boolean removed = removeNonActivatedUser(existingUser); + if (!removed) { + throw new EmailAlreadyUsedException(); + } + }); + User newUser = new User(); + String encryptedPassword = passwordEncoder.encode(password); + newUser.setLogin(userDTO.getLogin().toLowerCase()); + // new user gets initially a generated password + newUser.setPassword(encryptedPassword); + newUser.setFirstName(userDTO.getFirstName()); + newUser.setLastName(userDTO.getLastName()); + newUser.setEmail(userDTO.getEmail().toLowerCase()); + newUser.setImageUrl(userDTO.getImageUrl()); + newUser.setLangKey(userDTO.getLangKey()); + // new user is not active + newUser.setActivated(false); + // new user gets registration key + newUser.setActivationKey(RandomUtil.generateActivationKey()); + Set authorities = new HashSet<>(); + authorityRepository.findById(AuthoritiesConstants.USER).ifPresent(authorities::add); + newUser.setAuthorities(authorities); + userRepository.save(newUser); + log.debug("Created Information for User: {}", newUser); + return newUser; + } + + private boolean removeNonActivatedUser(User existingUser){ + if (existingUser.getActivated()) { + return false; + } + userRepository.delete(existingUser); + userRepository.flush(); + return true; + } + + public User createUser(UserDTO userDTO) { + User user = new User(); + user.setLogin(userDTO.getLogin().toLowerCase()); + user.setFirstName(userDTO.getFirstName()); + user.setLastName(userDTO.getLastName()); + user.setEmail(userDTO.getEmail().toLowerCase()); + user.setImageUrl(userDTO.getImageUrl()); + if (userDTO.getLangKey() == null) { + user.setLangKey(Constants.DEFAULT_LANGUAGE); // default language + } else { + user.setLangKey(userDTO.getLangKey()); + } + String encryptedPassword = passwordEncoder.encode(RandomUtil.generatePassword()); + user.setPassword(encryptedPassword); + user.setResetKey(RandomUtil.generateResetKey()); + user.setResetDate(Instant.now()); + user.setActivated(true); + if (userDTO.getAuthorities() != null) { + Set authorities = userDTO.getAuthorities().stream() + .map(authorityRepository::findById) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toSet()); + user.setAuthorities(authorities); + } + userRepository.save(user); + log.debug("Created Information for User: {}", user); + return user; + } + + /** + * Update basic information (first name, last name, email, language) for the current user. + * + * @param firstName first name of user + * @param lastName last name of user + * @param email email id of user + * @param langKey language key + * @param imageUrl image URL of user + */ + public void updateUser(String firstName, String lastName, String email, String langKey, String imageUrl) { + SecurityUtils.getCurrentUserLogin() + .flatMap(userRepository::findOneByLogin) + .ifPresent(user -> { + user.setFirstName(firstName); + user.setLastName(lastName); + user.setEmail(email.toLowerCase()); + user.setLangKey(langKey); + user.setImageUrl(imageUrl); + log.debug("Changed Information for User: {}", user); + }); + } + + /** + * Update all information for a specific user, and return the modified user. + * + * @param userDTO user to update + * @return updated user + */ + public Optional updateUser(UserDTO userDTO) { + return Optional.of(userRepository + .findById(userDTO.getId())) + .filter(Optional::isPresent) + .map(Optional::get) + .map(user -> { + user.setLogin(userDTO.getLogin().toLowerCase()); + user.setFirstName(userDTO.getFirstName()); + user.setLastName(userDTO.getLastName()); + user.setEmail(userDTO.getEmail().toLowerCase()); + user.setImageUrl(userDTO.getImageUrl()); + user.setActivated(userDTO.isActivated()); + user.setLangKey(userDTO.getLangKey()); + Set managedAuthorities = user.getAuthorities(); + managedAuthorities.clear(); + userDTO.getAuthorities().stream() + .map(authorityRepository::findById) + .filter(Optional::isPresent) + .map(Optional::get) + .forEach(managedAuthorities::add); + log.debug("Changed Information for User: {}", user); + return user; + }) + .map(UserDTO::new); + } + + public void deleteUser(String login) { + userRepository.findOneByLogin(login).ifPresent(user -> { + userRepository.delete(user); + log.debug("Deleted User: {}", user); + }); + } + + public void changePassword(String currentClearTextPassword, String newPassword) { + SecurityUtils.getCurrentUserLogin() + .flatMap(userRepository::findOneByLogin) + .ifPresent(user -> { + String currentEncryptedPassword = user.getPassword(); + if (!passwordEncoder.matches(currentClearTextPassword, currentEncryptedPassword)) { + throw new InvalidPasswordException(); + } + String encryptedPassword = passwordEncoder.encode(newPassword); + user.setPassword(encryptedPassword); + log.debug("Changed password for User: {}", user); + }); + } + + @Transactional(readOnly = true) + public Page getAllManagedUsers(Pageable pageable) { + return userRepository.findAllByLoginNot(pageable, Constants.ANONYMOUS_USER).map(UserDTO::new); + } + + @Transactional(readOnly = true) + public Optional getUserWithAuthoritiesByLogin(String login) { + return userRepository.findOneWithAuthoritiesByLogin(login); + } + + @Transactional(readOnly = true) + public Optional getUserWithAuthorities(Long id) { + return userRepository.findOneWithAuthoritiesById(id); + } + + @Transactional(readOnly = true) + public Optional getUserWithAuthorities() { + return SecurityUtils.getCurrentUserLogin().flatMap(userRepository::findOneWithAuthoritiesByLogin); + } + + /** + * Not activated users should be automatically deleted after 3 days. + *

+ * This is scheduled to get fired everyday, at 01:00 (am). + */ + @Scheduled(cron = "0 0 1 * * ?") + public void removeNotActivatedUsers() { + userRepository + .findAllByActivatedIsFalseAndCreatedDateBefore(Instant.now().minus(3, ChronoUnit.DAYS)) + .forEach(user -> { + log.debug("Deleting not activated user {}", user.getLogin()); + userRepository.delete(user); + }); + } + + /** + * @return a list of all the authorities + */ + public List getAuthorities() { + return authorityRepository.findAll().stream().map(Authority::getName).collect(Collectors.toList()); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/PasswordChangeDTO.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/PasswordChangeDTO.java new file mode 100644 index 0000000000..0711c97f44 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/PasswordChangeDTO.java @@ -0,0 +1,35 @@ +package com.baeldung.jhipster5.service.dto; + +/** + * A DTO representing a password change required data - current and new password. + */ +public class PasswordChangeDTO { + private String currentPassword; + private String newPassword; + + public PasswordChangeDTO() { + // Empty constructor needed for Jackson. + } + + public PasswordChangeDTO(String currentPassword, String newPassword) { + this.currentPassword = currentPassword; + this.newPassword = newPassword; + } + + public String getCurrentPassword() { + + return currentPassword; + } + + public void setCurrentPassword(String currentPassword) { + this.currentPassword = currentPassword; + } + + public String getNewPassword() { + return newPassword; + } + + public void setNewPassword(String newPassword) { + this.newPassword = newPassword; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/UserDTO.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/UserDTO.java new file mode 100644 index 0000000000..9142b3825e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/UserDTO.java @@ -0,0 +1,199 @@ +package com.baeldung.jhipster5.service.dto; + +import com.baeldung.jhipster5.config.Constants; + +import com.baeldung.jhipster5.domain.Authority; +import com.baeldung.jhipster5.domain.User; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; + +import javax.validation.constraints.*; +import java.time.Instant; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * A DTO representing a user, with his authorities. + */ +public class UserDTO { + + private Long id; + + @NotBlank + @Pattern(regexp = Constants.LOGIN_REGEX) + @Size(min = 1, max = 50) + private String login; + + @Size(max = 50) + private String firstName; + + @Size(max = 50) + private String lastName; + + @Email + @Size(min = 5, max = 254) + private String email; + + @Size(max = 256) + private String imageUrl; + + private boolean activated = false; + + @Size(min = 2, max = 6) + private String langKey; + + private String createdBy; + + private Instant createdDate; + + private String lastModifiedBy; + + private Instant lastModifiedDate; + + private Set authorities; + + public UserDTO() { + // Empty constructor needed for Jackson. + } + + public UserDTO(User user) { + this.id = user.getId(); + this.login = user.getLogin(); + this.firstName = user.getFirstName(); + this.lastName = user.getLastName(); + this.email = user.getEmail(); + this.activated = user.getActivated(); + this.imageUrl = user.getImageUrl(); + this.langKey = user.getLangKey(); + this.createdBy = user.getCreatedBy(); + this.createdDate = user.getCreatedDate(); + this.lastModifiedBy = user.getLastModifiedBy(); + this.lastModifiedDate = user.getLastModifiedDate(); + this.authorities = user.getAuthorities().stream() + .map(Authority::getName) + .collect(Collectors.toSet()); + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + public boolean isActivated() { + return activated; + } + + public void setActivated(boolean activated) { + this.activated = activated; + } + + public String getLangKey() { + return langKey; + } + + public void setLangKey(String langKey) { + this.langKey = langKey; + } + + public String getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + + public Instant getCreatedDate() { + return createdDate; + } + + public void setCreatedDate(Instant createdDate) { + this.createdDate = createdDate; + } + + public String getLastModifiedBy() { + return lastModifiedBy; + } + + public void setLastModifiedBy(String lastModifiedBy) { + this.lastModifiedBy = lastModifiedBy; + } + + public Instant getLastModifiedDate() { + return lastModifiedDate; + } + + public void setLastModifiedDate(Instant lastModifiedDate) { + this.lastModifiedDate = lastModifiedDate; + } + + public Set getAuthorities() { + return authorities; + } + + public void setAuthorities(Set authorities) { + this.authorities = authorities; + } + + @Override + public String toString() { + return "UserDTO{" + + "login='" + login + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", email='" + email + '\'' + + ", imageUrl='" + imageUrl + '\'' + + ", activated=" + activated + + ", langKey='" + langKey + '\'' + + ", createdBy=" + createdBy + + ", createdDate=" + createdDate + + ", lastModifiedBy='" + lastModifiedBy + '\'' + + ", lastModifiedDate=" + lastModifiedDate + + ", authorities=" + authorities + + "}"; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/package-info.java new file mode 100644 index 0000000000..87951796ea --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/package-info.java @@ -0,0 +1,4 @@ +/** + * Data Transfer Objects. + */ +package com.baeldung.jhipster5.service.dto; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/UserMapper.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/UserMapper.java new file mode 100644 index 0000000000..485c03813e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/UserMapper.java @@ -0,0 +1,81 @@ +package com.baeldung.jhipster5.service.mapper; + +import com.baeldung.jhipster5.domain.Authority; +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.service.dto.UserDTO; + +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Mapper for the entity User and its DTO called UserDTO. + * + * Normal mappers are generated using MapStruct, this one is hand-coded as MapStruct + * support is still in beta, and requires a manual step with an IDE. + */ +@Service +public class UserMapper { + + public List usersToUserDTOs(List users) { + return users.stream() + .filter(Objects::nonNull) + .map(this::userToUserDTO) + .collect(Collectors.toList()); + } + + public UserDTO userToUserDTO(User user) { + return new UserDTO(user); + } + + public List userDTOsToUsers(List userDTOs) { + return userDTOs.stream() + .filter(Objects::nonNull) + .map(this::userDTOToUser) + .collect(Collectors.toList()); + } + + public User userDTOToUser(UserDTO userDTO) { + if (userDTO == null) { + return null; + } else { + User user = new User(); + user.setId(userDTO.getId()); + user.setLogin(userDTO.getLogin()); + user.setFirstName(userDTO.getFirstName()); + user.setLastName(userDTO.getLastName()); + user.setEmail(userDTO.getEmail()); + user.setImageUrl(userDTO.getImageUrl()); + user.setActivated(userDTO.isActivated()); + user.setLangKey(userDTO.getLangKey()); + Set authorities = this.authoritiesFromStrings(userDTO.getAuthorities()); + user.setAuthorities(authorities); + return user; + } + } + + + private Set authoritiesFromStrings(Set authoritiesAsString) { + Set authorities = new HashSet<>(); + + if(authoritiesAsString != null){ + authorities = authoritiesAsString.stream().map(string -> { + Authority auth = new Authority(); + auth.setName(string); + return auth; + }).collect(Collectors.toSet()); + } + + return authorities; + } + + public User userFromId(Long id) { + if (id == null) { + return null; + } + User user = new User(); + user.setId(id); + return user; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/package-info.java new file mode 100644 index 0000000000..7d402321e7 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/package-info.java @@ -0,0 +1,4 @@ +/** + * MapStruct mappers for mapping domain objects and Data Transfer Objects. + */ +package com.baeldung.jhipster5.service.mapper; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/package-info.java new file mode 100644 index 0000000000..a54ed5cca0 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/package-info.java @@ -0,0 +1,4 @@ +/** + * Service layer beans. + */ +package com.baeldung.jhipster5.service; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/util/RandomUtil.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/util/RandomUtil.java new file mode 100644 index 0000000000..97e4d9c672 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/util/RandomUtil.java @@ -0,0 +1,41 @@ +package com.baeldung.jhipster5.service.util; + +import org.apache.commons.lang3.RandomStringUtils; + +/** + * Utility class for generating random Strings. + */ +public final class RandomUtil { + + private static final int DEF_COUNT = 20; + + private RandomUtil() { + } + + /** + * Generate a password. + * + * @return the generated password + */ + public static String generatePassword() { + return RandomStringUtils.randomAlphanumeric(DEF_COUNT); + } + + /** + * Generate an activation key. + * + * @return the generated activation key + */ + public static String generateActivationKey() { + return RandomStringUtils.randomNumeric(DEF_COUNT); + } + + /** + * Generate a reset key. + * + * @return the generated reset key + */ + public static String generateResetKey() { + return RandomStringUtils.randomNumeric(DEF_COUNT); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/AccountResource.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/AccountResource.java new file mode 100644 index 0000000000..2109e93999 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/AccountResource.java @@ -0,0 +1,179 @@ +package com.baeldung.jhipster5.web.rest; + + +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.repository.UserRepository; +import com.baeldung.jhipster5.security.SecurityUtils; +import com.baeldung.jhipster5.service.MailService; +import com.baeldung.jhipster5.service.UserService; +import com.baeldung.jhipster5.service.dto.PasswordChangeDTO; +import com.baeldung.jhipster5.service.dto.UserDTO; +import com.baeldung.jhipster5.web.rest.errors.*; +import com.baeldung.jhipster5.web.rest.vm.KeyAndPasswordVM; +import com.baeldung.jhipster5.web.rest.vm.ManagedUserVM; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import java.util.*; + +/** + * REST controller for managing the current user's account. + */ +@RestController +@RequestMapping("/api") +public class AccountResource { + + private final Logger log = LoggerFactory.getLogger(AccountResource.class); + + private final UserRepository userRepository; + + private final UserService userService; + + private final MailService mailService; + + public AccountResource(UserRepository userRepository, UserService userService, MailService mailService) { + + this.userRepository = userRepository; + this.userService = userService; + this.mailService = mailService; + } + + /** + * POST /register : register the user. + * + * @param managedUserVM the managed user View Model + * @throws InvalidPasswordException 400 (Bad Request) if the password is incorrect + * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already used + * @throws LoginAlreadyUsedException 400 (Bad Request) if the login is already used + */ + @PostMapping("/register") + @ResponseStatus(HttpStatus.CREATED) + public void registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM) { + if (!checkPasswordLength(managedUserVM.getPassword())) { + throw new InvalidPasswordException(); + } + User user = userService.registerUser(managedUserVM, managedUserVM.getPassword()); + mailService.sendActivationEmail(user); + } + + /** + * GET /activate : activate the registered user. + * + * @param key the activation key + * @throws RuntimeException 500 (Internal Server Error) if the user couldn't be activated + */ + @GetMapping("/activate") + public void activateAccount(@RequestParam(value = "key") String key) { + Optional user = userService.activateRegistration(key); + if (!user.isPresent()) { + throw new InternalServerErrorException("No user was found for this activation key"); + } + } + + /** + * GET /authenticate : check if the user is authenticated, and return its login. + * + * @param request the HTTP request + * @return the login if the user is authenticated + */ + @GetMapping("/authenticate") + public String isAuthenticated(HttpServletRequest request) { + log.debug("REST request to check if the current user is authenticated"); + return request.getRemoteUser(); + } + + /** + * GET /account : get the current user. + * + * @return the current user + * @throws RuntimeException 500 (Internal Server Error) if the user couldn't be returned + */ + @GetMapping("/account") + public UserDTO getAccount() { + return userService.getUserWithAuthorities() + .map(UserDTO::new) + .orElseThrow(() -> new InternalServerErrorException("User could not be found")); + } + + /** + * POST /account : update the current user information. + * + * @param userDTO the current user information + * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already used + * @throws RuntimeException 500 (Internal Server Error) if the user login wasn't found + */ + @PostMapping("/account") + public void saveAccount(@Valid @RequestBody UserDTO userDTO) { + String userLogin = SecurityUtils.getCurrentUserLogin().orElseThrow(() -> new InternalServerErrorException("Current user login not found")); + Optional existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()); + if (existingUser.isPresent() && (!existingUser.get().getLogin().equalsIgnoreCase(userLogin))) { + throw new EmailAlreadyUsedException(); + } + Optional user = userRepository.findOneByLogin(userLogin); + if (!user.isPresent()) { + throw new InternalServerErrorException("User could not be found"); + } + userService.updateUser(userDTO.getFirstName(), userDTO.getLastName(), userDTO.getEmail(), + userDTO.getLangKey(), userDTO.getImageUrl()); + } + + /** + * POST /account/change-password : changes the current user's password + * + * @param passwordChangeDto current and new password + * @throws InvalidPasswordException 400 (Bad Request) if the new password is incorrect + */ + @PostMapping(path = "/account/change-password") + public void changePassword(@RequestBody PasswordChangeDTO passwordChangeDto) { + if (!checkPasswordLength(passwordChangeDto.getNewPassword())) { + throw new InvalidPasswordException(); + } + userService.changePassword(passwordChangeDto.getCurrentPassword(), passwordChangeDto.getNewPassword()); + } + + /** + * POST /account/reset-password/init : Send an email to reset the password of the user + * + * @param mail the mail of the user + * @throws EmailNotFoundException 400 (Bad Request) if the email address is not registered + */ + @PostMapping(path = "/account/reset-password/init") + public void requestPasswordReset(@RequestBody String mail) { + mailService.sendPasswordResetMail( + userService.requestPasswordReset(mail) + .orElseThrow(EmailNotFoundException::new) + ); + } + + /** + * POST /account/reset-password/finish : Finish to reset the password of the user + * + * @param keyAndPassword the generated key and the new password + * @throws InvalidPasswordException 400 (Bad Request) if the password is incorrect + * @throws RuntimeException 500 (Internal Server Error) if the password could not be reset + */ + @PostMapping(path = "/account/reset-password/finish") + public void finishPasswordReset(@RequestBody KeyAndPasswordVM keyAndPassword) { + if (!checkPasswordLength(keyAndPassword.getNewPassword())) { + throw new InvalidPasswordException(); + } + Optional user = + userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey()); + + if (!user.isPresent()) { + throw new InternalServerErrorException("No user was found for this reset key"); + } + } + + private static boolean checkPasswordLength(String password) { + return !StringUtils.isEmpty(password) && + password.length() >= ManagedUserVM.PASSWORD_MIN_LENGTH && + password.length() <= ManagedUserVM.PASSWORD_MAX_LENGTH; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/AuditResource.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/AuditResource.java new file mode 100644 index 0000000000..d0182d5d9d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/AuditResource.java @@ -0,0 +1,77 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.service.AuditEventService; +import com.baeldung.jhipster5.web.rest.util.PaginationUtil; + +import io.github.jhipster.web.util.ResponseUtil; +import org.springframework.boot.actuate.audit.AuditEvent; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.List; + +/** + * REST controller for getting the audit events. + */ +@RestController +@RequestMapping("/management/audits") +public class AuditResource { + + private final AuditEventService auditEventService; + + public AuditResource(AuditEventService auditEventService) { + this.auditEventService = auditEventService; + } + + /** + * GET /audits : get a page of AuditEvents. + * + * @param pageable the pagination information + * @return the ResponseEntity with status 200 (OK) and the list of AuditEvents in body + */ + @GetMapping + public ResponseEntity> getAll(Pageable pageable) { + Page page = auditEventService.findAll(pageable); + HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/management/audits"); + return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK); + } + + /** + * GET /audits : get a page of AuditEvents between the fromDate and toDate. + * + * @param fromDate the start of the time period of AuditEvents to get + * @param toDate the end of the time period of AuditEvents to get + * @param pageable the pagination information + * @return the ResponseEntity with status 200 (OK) and the list of AuditEvents in body + */ + @GetMapping(params = {"fromDate", "toDate"}) + public ResponseEntity> getByDates( + @RequestParam(value = "fromDate") LocalDate fromDate, + @RequestParam(value = "toDate") LocalDate toDate, + Pageable pageable) { + + Page page = auditEventService.findByDates( + fromDate.atStartOfDay(ZoneId.systemDefault()).toInstant(), + toDate.atStartOfDay(ZoneId.systemDefault()).plusDays(1).toInstant(), + pageable); + HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/management/audits"); + return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK); + } + + /** + * GET /audits/:id : get an AuditEvent by id. + * + * @param id the id of the entity to get + * @return the ResponseEntity with status 200 (OK) and the AuditEvent in body, or status 404 (Not Found) + */ + @GetMapping("/{id:.+}") + public ResponseEntity get(@PathVariable Long id) { + return ResponseUtil.wrapOrNotFound(auditEventService.find(id)); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/LogsResource.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/LogsResource.java new file mode 100644 index 0000000000..f35b5f2d5c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/LogsResource.java @@ -0,0 +1,36 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.web.rest.vm.LoggerVM; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Controller for view and managing Log Level at runtime. + */ +@RestController +@RequestMapping("/management") +public class LogsResource { + + @GetMapping("/logs") + public List getList() { + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + return context.getLoggerList() + .stream() + .map(LoggerVM::new) + .collect(Collectors.toList()); + } + + @PutMapping("/logs") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void changeLevel(@RequestBody LoggerVM jsonLogger) { + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + context.getLogger(jsonLogger.getName()).setLevel(Level.valueOf(jsonLogger.getLevel())); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/UserJWTController.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/UserJWTController.java new file mode 100644 index 0000000000..aeea587089 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/UserJWTController.java @@ -0,0 +1,71 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.security.jwt.JWTFilter; +import com.baeldung.jhipster5.security.jwt.TokenProvider; +import com.baeldung.jhipster5.web.rest.vm.LoginVM; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +/** + * Controller to authenticate users. + */ +@RestController +@RequestMapping("/api") +public class UserJWTController { + + private final TokenProvider tokenProvider; + + private final AuthenticationManager authenticationManager; + + public UserJWTController(TokenProvider tokenProvider, AuthenticationManager authenticationManager) { + this.tokenProvider = tokenProvider; + this.authenticationManager = authenticationManager; + } + + @PostMapping("/authenticate") + public ResponseEntity authorize(@Valid @RequestBody LoginVM loginVM) { + + UsernamePasswordAuthenticationToken authenticationToken = + new UsernamePasswordAuthenticationToken(loginVM.getUsername(), loginVM.getPassword()); + + Authentication authentication = this.authenticationManager.authenticate(authenticationToken); + SecurityContextHolder.getContext().setAuthentication(authentication); + boolean rememberMe = (loginVM.isRememberMe() == null) ? false : loginVM.isRememberMe(); + String jwt = tokenProvider.createToken(authentication, rememberMe); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt); + return new ResponseEntity<>(new JWTToken(jwt), httpHeaders, HttpStatus.OK); + } + + /** + * Object to return as body in JWT Authentication. + */ + static class JWTToken { + + private String idToken; + + JWTToken(String idToken) { + this.idToken = idToken; + } + + @JsonProperty("id_token") + String getIdToken() { + return idToken; + } + + void setIdToken(String idToken) { + this.idToken = idToken; + } + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/UserResource.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/UserResource.java new file mode 100644 index 0000000000..a95acf6759 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/UserResource.java @@ -0,0 +1,183 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.config.Constants; +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.repository.UserRepository; +import com.baeldung.jhipster5.security.AuthoritiesConstants; +import com.baeldung.jhipster5.service.MailService; +import com.baeldung.jhipster5.service.UserService; +import com.baeldung.jhipster5.service.dto.UserDTO; +import com.baeldung.jhipster5.web.rest.errors.BadRequestAlertException; +import com.baeldung.jhipster5.web.rest.errors.EmailAlreadyUsedException; +import com.baeldung.jhipster5.web.rest.errors.LoginAlreadyUsedException; +import com.baeldung.jhipster5.web.rest.util.HeaderUtil; +import com.baeldung.jhipster5.web.rest.util.PaginationUtil; +import io.github.jhipster.web.util.ResponseUtil; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; + +/** + * REST controller for managing users. + *

+ * This class accesses the User entity, and needs to fetch its collection of authorities. + *

+ * For a normal use-case, it would be better to have an eager relationship between User and Authority, + * and send everything to the client side: there would be no View Model and DTO, a lot less code, and an outer-join + * which would be good for performance. + *

+ * We use a View Model and a DTO for 3 reasons: + *

    + *
  • We want to keep a lazy association between the user and the authorities, because people will + * quite often do relationships with the user, and we don't want them to get the authorities all + * the time for nothing (for performance reasons). This is the #1 goal: we should not impact our users' + * application because of this use-case.
  • + *
  • Not having an outer join causes n+1 requests to the database. This is not a real issue as + * we have by default a second-level cache. This means on the first HTTP call we do the n+1 requests, + * but then all authorities come from the cache, so in fact it's much better than doing an outer join + * (which will get lots of data from the database, for each HTTP call).
  • + *
  • As this manages users, for security reasons, we'd rather have a DTO layer.
  • + *
+ *

+ * Another option would be to have a specific JPA entity graph to handle this case. + */ +@RestController +@RequestMapping("/api") +public class UserResource { + + private final Logger log = LoggerFactory.getLogger(UserResource.class); + + private final UserService userService; + + private final UserRepository userRepository; + + private final MailService mailService; + + public UserResource(UserService userService, UserRepository userRepository, MailService mailService) { + + this.userService = userService; + this.userRepository = userRepository; + this.mailService = mailService; + } + + /** + * POST /users : Creates a new user. + *

+ * Creates a new user if the login and email are not already used, and sends an + * mail with an activation link. + * The user needs to be activated on creation. + * + * @param userDTO the user to create + * @return the ResponseEntity with status 201 (Created) and with body the new user, or with status 400 (Bad Request) if the login or email is already in use + * @throws URISyntaxException if the Location URI syntax is incorrect + * @throws BadRequestAlertException 400 (Bad Request) if the login or email is already in use + */ + @PostMapping("/users") + @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")") + public ResponseEntity createUser(@Valid @RequestBody UserDTO userDTO) throws URISyntaxException { + log.debug("REST request to save User : {}", userDTO); + + if (userDTO.getId() != null) { + throw new BadRequestAlertException("A new user cannot already have an ID", "userManagement", "idexists"); + // Lowercase the user login before comparing with database + } else if (userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()).isPresent()) { + throw new LoginAlreadyUsedException(); + } else if (userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()).isPresent()) { + throw new EmailAlreadyUsedException(); + } else { + User newUser = userService.createUser(userDTO); + mailService.sendCreationEmail(newUser); + return ResponseEntity.created(new URI("/api/users/" + newUser.getLogin())) + .headers(HeaderUtil.createAlert( "A user is created with identifier " + newUser.getLogin(), newUser.getLogin())) + .body(newUser); + } + } + + /** + * PUT /users : Updates an existing User. + * + * @param userDTO the user to update + * @return the ResponseEntity with status 200 (OK) and with body the updated user + * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already in use + * @throws LoginAlreadyUsedException 400 (Bad Request) if the login is already in use + */ + @PutMapping("/users") + @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")") + public ResponseEntity updateUser(@Valid @RequestBody UserDTO userDTO) { + log.debug("REST request to update User : {}", userDTO); + Optional existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()); + if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) { + throw new EmailAlreadyUsedException(); + } + existingUser = userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()); + if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) { + throw new LoginAlreadyUsedException(); + } + Optional updatedUser = userService.updateUser(userDTO); + + return ResponseUtil.wrapOrNotFound(updatedUser, + HeaderUtil.createAlert("A user is updated with identifier " + userDTO.getLogin(), userDTO.getLogin())); + } + + /** + * GET /users : get all users. + * + * @param pageable the pagination information + * @return the ResponseEntity with status 200 (OK) and with body all users + */ + @GetMapping("/users") + public ResponseEntity> getAllUsers(Pageable pageable) { + final Page page = userService.getAllManagedUsers(pageable); + HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/users"); + return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK); + } + + /** + * @return a string list of the all of the roles + */ + @GetMapping("/users/authorities") + @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")") + public List getAuthorities() { + return userService.getAuthorities(); + } + + /** + * GET /users/:login : get the "login" user. + * + * @param login the login of the user to find + * @return the ResponseEntity with status 200 (OK) and with body the "login" user, or with status 404 (Not Found) + */ + @GetMapping("/users/{login:" + Constants.LOGIN_REGEX + "}") + public ResponseEntity getUser(@PathVariable String login) { + log.debug("REST request to get User : {}", login); + return ResponseUtil.wrapOrNotFound( + userService.getUserWithAuthoritiesByLogin(login) + .map(UserDTO::new)); + } + + /** + * DELETE /users/:login : delete the "login" User. + * + * @param login the login of the user to delete + * @return the ResponseEntity with status 200 (OK) + */ + @DeleteMapping("/users/{login:" + Constants.LOGIN_REGEX + "}") + @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")") + public ResponseEntity deleteUser(@PathVariable String login) { + log.debug("REST request to delete User: {}", login); + userService.deleteUser(login); + return ResponseEntity.ok().headers(HeaderUtil.createAlert( "A user is deleted with identifier " + login, login)).build(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/BadRequestAlertException.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/BadRequestAlertException.java new file mode 100644 index 0000000000..c4c403351a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/BadRequestAlertException.java @@ -0,0 +1,42 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import org.zalando.problem.AbstractThrowableProblem; +import org.zalando.problem.Status; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +public class BadRequestAlertException extends AbstractThrowableProblem { + + private static final long serialVersionUID = 1L; + + private final String entityName; + + private final String errorKey; + + public BadRequestAlertException(String defaultMessage, String entityName, String errorKey) { + this(ErrorConstants.DEFAULT_TYPE, defaultMessage, entityName, errorKey); + } + + public BadRequestAlertException(URI type, String defaultMessage, String entityName, String errorKey) { + super(type, defaultMessage, Status.BAD_REQUEST, null, null, null, getAlertParameters(entityName, errorKey)); + this.entityName = entityName; + this.errorKey = errorKey; + } + + public String getEntityName() { + return entityName; + } + + public String getErrorKey() { + return errorKey; + } + + private static Map getAlertParameters(String entityName, String errorKey) { + Map parameters = new HashMap<>(); + parameters.put("message", "error." + errorKey); + parameters.put("params", entityName); + return parameters; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/CustomParameterizedException.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/CustomParameterizedException.java new file mode 100644 index 0000000000..8c3df82b83 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/CustomParameterizedException.java @@ -0,0 +1,54 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import org.zalando.problem.AbstractThrowableProblem; + +import java.util.HashMap; +import java.util.Map; + +import static org.zalando.problem.Status.BAD_REQUEST; + +/** + * Custom, parameterized exception, which can be translated on the client side. + * For example: + * + *

+ * throw new CustomParameterizedException("myCustomError", "hello", "world");
+ * 
+ * + * Can be translated with: + * + *
+ * "error.myCustomError" :  "The server says {{param0}} to {{param1}}"
+ * 
+ */ +public class CustomParameterizedException extends AbstractThrowableProblem { + + private static final long serialVersionUID = 1L; + + private static final String PARAM = "param"; + + public CustomParameterizedException(String message, String... params) { + this(message, toParamMap(params)); + } + + public CustomParameterizedException(String message, Map paramMap) { + super(ErrorConstants.PARAMETERIZED_TYPE, "Parameterized Exception", BAD_REQUEST, null, null, null, toProblemParameters(message, paramMap)); + } + + public static Map toParamMap(String... params) { + Map paramMap = new HashMap<>(); + if (params != null && params.length > 0) { + for (int i = 0; i < params.length; i++) { + paramMap.put(PARAM + i, params[i]); + } + } + return paramMap; + } + + public static Map toProblemParameters(String message, Map paramMap) { + Map parameters = new HashMap<>(); + parameters.put("message", message); + parameters.put("params", paramMap); + return parameters; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/EmailAlreadyUsedException.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/EmailAlreadyUsedException.java new file mode 100644 index 0000000000..b3dcc0279e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/EmailAlreadyUsedException.java @@ -0,0 +1,10 @@ +package com.baeldung.jhipster5.web.rest.errors; + +public class EmailAlreadyUsedException extends BadRequestAlertException { + + private static final long serialVersionUID = 1L; + + public EmailAlreadyUsedException() { + super(ErrorConstants.EMAIL_ALREADY_USED_TYPE, "Email is already in use!", "userManagement", "emailexists"); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/EmailNotFoundException.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/EmailNotFoundException.java new file mode 100644 index 0000000000..b93081cacb --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/EmailNotFoundException.java @@ -0,0 +1,13 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import org.zalando.problem.AbstractThrowableProblem; +import org.zalando.problem.Status; + +public class EmailNotFoundException extends AbstractThrowableProblem { + + private static final long serialVersionUID = 1L; + + public EmailNotFoundException() { + super(ErrorConstants.EMAIL_NOT_FOUND_TYPE, "Email address not registered", Status.BAD_REQUEST); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/ErrorConstants.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/ErrorConstants.java new file mode 100644 index 0000000000..06be9254a9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/ErrorConstants.java @@ -0,0 +1,21 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import java.net.URI; + +public final class ErrorConstants { + + public static final String ERR_CONCURRENCY_FAILURE = "error.concurrencyFailure"; + public static final String ERR_VALIDATION = "error.validation"; + public static final String PROBLEM_BASE_URL = "https://www.jhipster.tech/problem"; + public static final URI DEFAULT_TYPE = URI.create(PROBLEM_BASE_URL + "/problem-with-message"); + public static final URI CONSTRAINT_VIOLATION_TYPE = URI.create(PROBLEM_BASE_URL + "/constraint-violation"); + public static final URI PARAMETERIZED_TYPE = URI.create(PROBLEM_BASE_URL + "/parameterized"); + public static final URI ENTITY_NOT_FOUND_TYPE = URI.create(PROBLEM_BASE_URL + "/entity-not-found"); + public static final URI INVALID_PASSWORD_TYPE = URI.create(PROBLEM_BASE_URL + "/invalid-password"); + public static final URI EMAIL_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/email-already-used"); + public static final URI LOGIN_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/login-already-used"); + public static final URI EMAIL_NOT_FOUND_TYPE = URI.create(PROBLEM_BASE_URL + "/email-not-found"); + + private ErrorConstants() { + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslator.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslator.java new file mode 100644 index 0000000000..3f7cc6b565 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslator.java @@ -0,0 +1,112 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import com.baeldung.jhipster5.web.rest.util.HeaderUtil; + +import org.springframework.dao.ConcurrencyFailureException; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.NativeWebRequest; +import org.zalando.problem.DefaultProblem; +import org.zalando.problem.Problem; +import org.zalando.problem.ProblemBuilder; +import org.zalando.problem.Status; +import org.zalando.problem.spring.web.advice.ProblemHandling; +import org.zalando.problem.violations.ConstraintViolationProblem; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.stream.Collectors; + +/** + * Controller advice to translate the server side exceptions to client-friendly json structures. + * The error response follows RFC7807 - Problem Details for HTTP APIs (https://tools.ietf.org/html/rfc7807) + */ +@ControllerAdvice +public class ExceptionTranslator implements ProblemHandling { + + private static final String FIELD_ERRORS_KEY = "fieldErrors"; + private static final String MESSAGE_KEY = "message"; + private static final String PATH_KEY = "path"; + private static final String VIOLATIONS_KEY = "violations"; + + /** + * Post-process the Problem payload to add the message key for the front-end if needed + */ + @Override + public ResponseEntity process(@Nullable ResponseEntity entity, NativeWebRequest request) { + if (entity == null) { + return entity; + } + Problem problem = entity.getBody(); + if (!(problem instanceof ConstraintViolationProblem || problem instanceof DefaultProblem)) { + return entity; + } + ProblemBuilder builder = Problem.builder() + .withType(Problem.DEFAULT_TYPE.equals(problem.getType()) ? ErrorConstants.DEFAULT_TYPE : problem.getType()) + .withStatus(problem.getStatus()) + .withTitle(problem.getTitle()) + .with(PATH_KEY, request.getNativeRequest(HttpServletRequest.class).getRequestURI()); + + if (problem instanceof ConstraintViolationProblem) { + builder + .with(VIOLATIONS_KEY, ((ConstraintViolationProblem) problem).getViolations()) + .with(MESSAGE_KEY, ErrorConstants.ERR_VALIDATION); + } else { + builder + .withCause(((DefaultProblem) problem).getCause()) + .withDetail(problem.getDetail()) + .withInstance(problem.getInstance()); + problem.getParameters().forEach(builder::with); + if (!problem.getParameters().containsKey(MESSAGE_KEY) && problem.getStatus() != null) { + builder.with(MESSAGE_KEY, "error.http." + problem.getStatus().getStatusCode()); + } + } + return new ResponseEntity<>(builder.build(), entity.getHeaders(), entity.getStatusCode()); + } + + @Override + public ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidException ex, @Nonnull NativeWebRequest request) { + BindingResult result = ex.getBindingResult(); + List fieldErrors = result.getFieldErrors().stream() + .map(f -> new FieldErrorVM(f.getObjectName(), f.getField(), f.getCode())) + .collect(Collectors.toList()); + + Problem problem = Problem.builder() + .withType(ErrorConstants.CONSTRAINT_VIOLATION_TYPE) + .withTitle("Method argument not valid") + .withStatus(defaultConstraintViolationStatus()) + .with(MESSAGE_KEY, ErrorConstants.ERR_VALIDATION) + .with(FIELD_ERRORS_KEY, fieldErrors) + .build(); + return create(ex, problem, request); + } + + @ExceptionHandler + public ResponseEntity handleNoSuchElementException(NoSuchElementException ex, NativeWebRequest request) { + Problem problem = Problem.builder() + .withStatus(Status.NOT_FOUND) + .with(MESSAGE_KEY, ErrorConstants.ENTITY_NOT_FOUND_TYPE) + .build(); + return create(ex, problem, request); + } + + @ExceptionHandler + public ResponseEntity handleBadRequestAlertException(BadRequestAlertException ex, NativeWebRequest request) { + return create(ex, request, HeaderUtil.createFailureAlert(ex.getEntityName(), ex.getErrorKey(), ex.getMessage())); + } + + @ExceptionHandler + public ResponseEntity handleConcurrencyFailure(ConcurrencyFailureException ex, NativeWebRequest request) { + Problem problem = Problem.builder() + .withStatus(Status.CONFLICT) + .with(MESSAGE_KEY, ErrorConstants.ERR_CONCURRENCY_FAILURE) + .build(); + return create(ex, problem, request); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/FieldErrorVM.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/FieldErrorVM.java new file mode 100644 index 0000000000..349f548850 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/FieldErrorVM.java @@ -0,0 +1,33 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import java.io.Serializable; + +public class FieldErrorVM implements Serializable { + + private static final long serialVersionUID = 1L; + + private final String objectName; + + private final String field; + + private final String message; + + public FieldErrorVM(String dto, String field, String message) { + this.objectName = dto; + this.field = field; + this.message = message; + } + + public String getObjectName() { + return objectName; + } + + public String getField() { + return field; + } + + public String getMessage() { + return message; + } + +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/InternalServerErrorException.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/InternalServerErrorException.java new file mode 100644 index 0000000000..13e128237b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/InternalServerErrorException.java @@ -0,0 +1,16 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import org.zalando.problem.AbstractThrowableProblem; +import org.zalando.problem.Status; + +/** + * Simple exception with a message, that returns an Internal Server Error code. + */ +public class InternalServerErrorException extends AbstractThrowableProblem { + + private static final long serialVersionUID = 1L; + + public InternalServerErrorException(String message) { + super(ErrorConstants.DEFAULT_TYPE, message, Status.INTERNAL_SERVER_ERROR); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/InvalidPasswordException.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/InvalidPasswordException.java new file mode 100644 index 0000000000..6bb91247ff --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/InvalidPasswordException.java @@ -0,0 +1,13 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import org.zalando.problem.AbstractThrowableProblem; +import org.zalando.problem.Status; + +public class InvalidPasswordException extends AbstractThrowableProblem { + + private static final long serialVersionUID = 1L; + + public InvalidPasswordException() { + super(ErrorConstants.INVALID_PASSWORD_TYPE, "Incorrect password", Status.BAD_REQUEST); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/LoginAlreadyUsedException.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/LoginAlreadyUsedException.java new file mode 100644 index 0000000000..987a94193d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/LoginAlreadyUsedException.java @@ -0,0 +1,10 @@ +package com.baeldung.jhipster5.web.rest.errors; + +public class LoginAlreadyUsedException extends BadRequestAlertException { + + private static final long serialVersionUID = 1L; + + public LoginAlreadyUsedException() { + super(ErrorConstants.LOGIN_ALREADY_USED_TYPE, "Login name already used!", "userManagement", "userexists"); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/package-info.java new file mode 100644 index 0000000000..7f57af4429 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/errors/package-info.java @@ -0,0 +1,6 @@ +/** + * Specific errors used with Zalando's "problem-spring-web" library. + * + * More information on https://github.com/zalando/problem-spring-web + */ +package com.baeldung.jhipster5.web.rest.errors; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/package-info.java new file mode 100644 index 0000000000..75bf6840f6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/package-info.java @@ -0,0 +1,4 @@ +/** + * Spring MVC REST controllers. + */ +package com.baeldung.jhipster5.web.rest; diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/util/HeaderUtil.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/util/HeaderUtil.java new file mode 100644 index 0000000000..91fdd68261 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/util/HeaderUtil.java @@ -0,0 +1,45 @@ +package com.baeldung.jhipster5.web.rest.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; + +/** + * Utility class for HTTP headers creation. + */ +public final class HeaderUtil { + + private static final Logger log = LoggerFactory.getLogger(HeaderUtil.class); + + private static final String APPLICATION_NAME = "bookstoreApp"; + + private HeaderUtil() { + } + + public static HttpHeaders createAlert(String message, String param) { + HttpHeaders headers = new HttpHeaders(); + headers.add("X-" + APPLICATION_NAME + "-alert", message); + headers.add("X-" + APPLICATION_NAME + "-params", param); + return headers; + } + + public static HttpHeaders createEntityCreationAlert(String entityName, String param) { + return createAlert("A new " + entityName + " is created with identifier " + param, param); + } + + public static HttpHeaders createEntityUpdateAlert(String entityName, String param) { + return createAlert("A " + entityName + " is updated with identifier " + param, param); + } + + public static HttpHeaders createEntityDeletionAlert(String entityName, String param) { + return createAlert("A " + entityName + " is deleted with identifier " + param, param); + } + + public static HttpHeaders createFailureAlert(String entityName, String errorKey, String defaultMessage) { + log.error("Entity processing failed, {}", defaultMessage); + HttpHeaders headers = new HttpHeaders(); + headers.add("X-" + APPLICATION_NAME + "-error", defaultMessage); + headers.add("X-" + APPLICATION_NAME + "-params", entityName); + return headers; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/util/PaginationUtil.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/util/PaginationUtil.java new file mode 100644 index 0000000000..9928dbe171 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/util/PaginationUtil.java @@ -0,0 +1,45 @@ +package com.baeldung.jhipster5.web.rest.util; + +import org.springframework.data.domain.Page; +import org.springframework.http.HttpHeaders; +import org.springframework.web.util.UriComponentsBuilder; + +/** + * Utility class for handling pagination. + * + *

+ * Pagination uses the same principles as the GitHub API, + * and follow RFC 5988 (Link header). + */ +public final class PaginationUtil { + + private PaginationUtil() { + } + + public static HttpHeaders generatePaginationHttpHeaders(Page page, String baseUrl) { + + HttpHeaders headers = new HttpHeaders(); + headers.add("X-Total-Count", Long.toString(page.getTotalElements())); + String link = ""; + if ((page.getNumber() + 1) < page.getTotalPages()) { + link = "<" + generateUri(baseUrl, page.getNumber() + 1, page.getSize()) + ">; rel=\"next\","; + } + // prev link + if ((page.getNumber()) > 0) { + link += "<" + generateUri(baseUrl, page.getNumber() - 1, page.getSize()) + ">; rel=\"prev\","; + } + // last and first link + int lastPage = 0; + if (page.getTotalPages() > 0) { + lastPage = page.getTotalPages() - 1; + } + link += "<" + generateUri(baseUrl, lastPage, page.getSize()) + ">; rel=\"last\","; + link += "<" + generateUri(baseUrl, 0, page.getSize()) + ">; rel=\"first\""; + headers.add(HttpHeaders.LINK, link); + return headers; + } + + private static String generateUri(String baseUrl, int page, int size) { + return UriComponentsBuilder.fromUriString(baseUrl).queryParam("page", page).queryParam("size", size).toUriString(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/KeyAndPasswordVM.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/KeyAndPasswordVM.java new file mode 100644 index 0000000000..840fa02cfc --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/KeyAndPasswordVM.java @@ -0,0 +1,27 @@ +package com.baeldung.jhipster5.web.rest.vm; + +/** + * View Model object for storing the user's key and password. + */ +public class KeyAndPasswordVM { + + private String key; + + private String newPassword; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getNewPassword() { + return newPassword; + } + + public void setNewPassword(String newPassword) { + this.newPassword = newPassword; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/LoggerVM.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/LoggerVM.java new file mode 100644 index 0000000000..952e7df298 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/LoggerVM.java @@ -0,0 +1,46 @@ +package com.baeldung.jhipster5.web.rest.vm; + +import ch.qos.logback.classic.Logger; + +/** + * View Model object for storing a Logback logger. + */ +public class LoggerVM { + + private String name; + + private String level; + + public LoggerVM(Logger logger) { + this.name = logger.getName(); + this.level = logger.getEffectiveLevel().toString(); + } + + public LoggerVM() { + // Empty public constructor used by Jackson. + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLevel() { + return level; + } + + public void setLevel(String level) { + this.level = level; + } + + @Override + public String toString() { + return "LoggerVM{" + + "name='" + name + '\'' + + ", level='" + level + '\'' + + '}'; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/LoginVM.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/LoginVM.java new file mode 100644 index 0000000000..8fc119ab69 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/LoginVM.java @@ -0,0 +1,52 @@ +package com.baeldung.jhipster5.web.rest.vm; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +/** + * View Model object for storing a user's credentials. + */ +public class LoginVM { + + @NotNull + @Size(min = 1, max = 50) + private String username; + + @NotNull + @Size(min = ManagedUserVM.PASSWORD_MIN_LENGTH, max = ManagedUserVM.PASSWORD_MAX_LENGTH) + private String password; + + private Boolean rememberMe; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Boolean isRememberMe() { + return rememberMe; + } + + public void setRememberMe(Boolean rememberMe) { + this.rememberMe = rememberMe; + } + + @Override + public String toString() { + return "LoginVM{" + + "username='" + username + '\'' + + ", rememberMe=" + rememberMe + + '}'; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/ManagedUserVM.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/ManagedUserVM.java new file mode 100644 index 0000000000..314577c456 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/ManagedUserVM.java @@ -0,0 +1,35 @@ +package com.baeldung.jhipster5.web.rest.vm; + +import com.baeldung.jhipster5.service.dto.UserDTO; +import javax.validation.constraints.Size; + +/** + * View Model extending the UserDTO, which is meant to be used in the user management UI. + */ +public class ManagedUserVM extends UserDTO { + + public static final int PASSWORD_MIN_LENGTH = 4; + + public static final int PASSWORD_MAX_LENGTH = 100; + + @Size(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH) + private String password; + + public ManagedUserVM() { + // Empty constructor needed for Jackson. + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return "ManagedUserVM{" + + "} " + super.toString(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/package-info.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/package-info.java new file mode 100644 index 0000000000..ff58799037 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/vm/package-info.java @@ -0,0 +1,4 @@ +/** + * View Models used by Spring MVC REST controllers. + */ +package com.baeldung.jhipster5.web.rest.vm; diff --git a/jhipster-5/bookstore-monolith/src/main/jib/entrypoint.sh b/jhipster-5/bookstore-monolith/src/main/jib/entrypoint.sh new file mode 100644 index 0000000000..b3c4541011 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/jib/entrypoint.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "The application will start in ${JHIPSTER_SLEEP}s..." && sleep ${JHIPSTER_SLEEP} +exec java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -cp /app/resources/:/app/classes/:/app/libs/* "com.baeldung.jhipster5.BookstoreApp" "$@" diff --git a/jhipster-5/bookstore-monolith/src/main/resources/.h2.server.properties b/jhipster-5/bookstore-monolith/src/main/resources/.h2.server.properties new file mode 100644 index 0000000000..99767b3a8a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/.h2.server.properties @@ -0,0 +1,5 @@ +#H2 Server Properties +0=JHipster H2 (Memory)|org.h2.Driver|jdbc\:h2\:mem\:bookstore|Bookstore +webAllowOthers=true +webPort=8082 +webSSL=false diff --git a/jhipster-5/bookstore-monolith/src/main/resources/banner.txt b/jhipster-5/bookstore-monolith/src/main/resources/banner.txt new file mode 100644 index 0000000000..e0bc55aaff --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/banner.txt @@ -0,0 +1,10 @@ + + ${AnsiColor.GREEN} ██╗${AnsiColor.RED} ██╗ ██╗ ████████╗ ███████╗ ██████╗ ████████╗ ████████╗ ███████╗ + ${AnsiColor.GREEN} ██║${AnsiColor.RED} ██║ ██║ ╚══██╔══╝ ██╔═══██╗ ██╔════╝ ╚══██╔══╝ ██╔═════╝ ██╔═══██╗ + ${AnsiColor.GREEN} ██║${AnsiColor.RED} ████████║ ██║ ███████╔╝ ╚█████╗ ██║ ██████╗ ███████╔╝ + ${AnsiColor.GREEN}██╗ ██║${AnsiColor.RED} ██╔═══██║ ██║ ██╔════╝ ╚═══██╗ ██║ ██╔═══╝ ██╔══██║ + ${AnsiColor.GREEN}╚██████╔╝${AnsiColor.RED} ██║ ██║ ████████╗ ██║ ██████╔╝ ██║ ████████╗ ██║ ╚██╗ + ${AnsiColor.GREEN} ╚═════╝ ${AnsiColor.RED} ╚═╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═╝ + +${AnsiColor.BRIGHT_BLUE}:: JHipster 🤓 :: Running Spring Boot ${spring-boot.version} :: +:: https://www.jhipster.tech ::${AnsiColor.DEFAULT} diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/application-dev.yml b/jhipster-5/bookstore-monolith/src/main/resources/config/application-dev.yml new file mode 100644 index 0000000000..64742feb45 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/application-dev.yml @@ -0,0 +1,122 @@ +# =================================================================== +# Spring Boot configuration for the "dev" profile. +# +# This configuration overrides the application.yml file. +# +# More information on profiles: https://www.jhipster.tech/profiles/ +# More information on configuration properties: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +# =================================================================== +# Standard Spring Boot properties. +# Full reference is available at: +# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html +# =================================================================== + +logging: + level: + ROOT: DEBUG + io.github.jhipster: DEBUG + com.baeldung.jhipster5: DEBUG + +spring: + profiles: + active: dev + include: + - swagger + # Uncomment to activate TLS for the dev profile + #- tls + devtools: + restart: + enabled: true + additional-exclude: .h2.server.properties + livereload: + enabled: false # we use Webpack dev server + BrowserSync for livereload + jackson: + serialization: + indent-output: true + datasource: + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:h2:mem:bookstore;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + username: Bookstore + password: + hikari: + poolName: Hikari + auto-commit: false + h2: + console: + enabled: false + jpa: + database-platform: io.github.jhipster.domain.util.FixedH2Dialect + database: H2 + show-sql: true + properties: + hibernate.id.new_generator_mappings: true + hibernate.connection.provider_disables_autocommit: true + hibernate.cache.use_second_level_cache: false + hibernate.cache.use_query_cache: false + hibernate.generate_statistics: true + liquibase: + contexts: dev + mail: + host: localhost + port: 25 + username: + password: + messages: + cache-duration: PT1S # 1 second, see the ISO 8601 standard + thymeleaf: + cache: false + +server: + port: 8080 + +# =================================================================== +# JHipster specific properties +# +# Full reference is available at: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +jhipster: + http: + version: V_1_1 # To use HTTP/2 you will need to activate TLS (see application-tls.yml) + # CORS is only enabled by default with the "dev" profile, so BrowserSync can access the API + cors: + allowed-origins: "*" + allowed-methods: "*" + allowed-headers: "*" + exposed-headers: "Authorization,Link,X-Total-Count" + allow-credentials: true + max-age: 1800 + security: + authentication: + jwt: + # This token must be encoded using Base64 and be at least 256 bits long (you can type `openssl rand -base64 64` on your command line to generate a 512 bits one) + base64-secret: NDJmOTVlZjI2NzhlZDRjNmVkNTM1NDE2NjkyNDljZDJiNzBlMjI5YmZjMjY3MzdjZmZlMjI3NjE4OTRkNzc5MWYzNDNlYWMzYmJjOWRmMjc5ZWQyZTZmOWZkOTMxZWZhNWE1MTVmM2U2NjFmYjhlNDc2Y2Q3NzliMGY0YzFkNmI= + # Token is valid 24 hours + token-validity-in-seconds: 86400 + token-validity-in-seconds-for-remember-me: 2592000 + mail: # specific JHipster mail property, for standard properties see MailProperties + from: Bookstore@localhost + base-url: http://127.0.0.1:8080 + metrics: + logs: # Reports metrics in the logs + enabled: false + report-frequency: 60 # in seconds + logging: + logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration + enabled: false + host: localhost + port: 5000 + queue-size: 512 + +# =================================================================== +# Application specific properties +# Add your own application properties here, see the ApplicationProperties class +# to have type-safe configuration, like in the JHipsterProperties above +# +# More documentation is available at: +# https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +# application: diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/application-prod.yml b/jhipster-5/bookstore-monolith/src/main/resources/config/application-prod.yml new file mode 100644 index 0000000000..d698099fac --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/application-prod.yml @@ -0,0 +1,133 @@ +# =================================================================== +# Spring Boot configuration for the "prod" profile. +# +# This configuration overrides the application.yml file. +# +# More information on profiles: https://www.jhipster.tech/profiles/ +# More information on configuration properties: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +# =================================================================== +# Standard Spring Boot properties. +# Full reference is available at: +# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html +# =================================================================== + +logging: + level: + ROOT: INFO + com.baeldung.jhipster5: INFO + io.github.jhipster: INFO + +spring: + devtools: + restart: + enabled: false + livereload: + enabled: false + datasource: + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:mysql://localhost:3306/Bookstore?useUnicode=true&characterEncoding=utf8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC + username: root + password: + hikari: + poolName: Hikari + auto-commit: false + data-source-properties: + cachePrepStmts: true + prepStmtCacheSize: 250 + prepStmtCacheSqlLimit: 2048 + useServerPrepStmts: true + jpa: + database-platform: org.hibernate.dialect.MySQL5InnoDBDialect + database: MYSQL + show-sql: false + properties: + hibernate.id.new_generator_mappings: true + hibernate.connection.provider_disables_autocommit: true + hibernate.cache.use_second_level_cache: false + hibernate.cache.use_query_cache: false + hibernate.generate_statistics: true + liquibase: + contexts: prod + mail: + host: localhost + port: 25 + username: + password: + thymeleaf: + cache: true + +# =================================================================== +# To enable TLS in production, generate a certificate using: +# keytool -genkey -alias bookstore -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650 +# +# You can also use Let's Encrypt: +# https://maximilian-boehm.com/hp2121/Create-a-Java-Keystore-JKS-from-Let-s-Encrypt-Certificates.htm +# +# Then, modify the server.ssl properties so your "server" configuration looks like: +# +# server: +# port: 443 +# ssl: +# key-store: classpath:config/tls/keystore.p12 +# key-store-password: password +# key-store-type: PKCS12 +# key-alias: bookstore +# # The ciphers suite enforce the security by deactivating some old and deprecated SSL cipher, this list was tested against SSL Labs (https://www.ssllabs.com/ssltest/) +# ciphers: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA +# =================================================================== +server: + port: 8080 + compression: + enabled: true + mime-types: text/html,text/xml,text/plain,text/css, application/javascript, application/json + min-response-size: 1024 + +# =================================================================== +# JHipster specific properties +# +# Full reference is available at: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +jhipster: + http: + version: V_1_1 # To use HTTP/2 you will need SSL support (see above the "server.ssl" configuration) + cache: # Used by the CachingHttpHeadersFilter + timeToLiveInDays: 1461 + security: + authentication: + jwt: + # This token must be encoded using Base64 and be at least 256 bits long (you can type `openssl rand -base64 64` on your command line to generate a 512 bits one) + # As this is the PRODUCTION configuration, you MUST change the default key, and store it securely: + # - In the JHipster Registry (which includes a Spring Cloud Config server) + # - In a separate `application-prod.yml` file, in the same folder as your executable WAR file + # - In the `JHIPSTER_SECURITY_AUTHENTICATION_JWT_BASE64_SECRET` environment variable + base64-secret: NDJmOTVlZjI2NzhlZDRjNmVkNTM1NDE2NjkyNDljZDJiNzBlMjI5YmZjMjY3MzdjZmZlMjI3NjE4OTRkNzc5MWYzNDNlYWMzYmJjOWRmMjc5ZWQyZTZmOWZkOTMxZWZhNWE1MTVmM2U2NjFmYjhlNDc2Y2Q3NzliMGY0YzFkNmI= + # Token is valid 24 hours + token-validity-in-seconds: 86400 + token-validity-in-seconds-for-remember-me: 2592000 + mail: # specific JHipster mail property, for standard properties see MailProperties + from: Bookstore@localhost + base-url: http://my-server-url-to-change # Modify according to your server's URL + metrics: + logs: # Reports metrics in the logs + enabled: false + report-frequency: 60 # in seconds + logging: + logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration + enabled: false + host: localhost + port: 5000 + queue-size: 512 + +# =================================================================== +# Application specific properties +# Add your own application properties here, see the ApplicationProperties class +# to have type-safe configuration, like in the JHipsterProperties above +# +# More documentation is available at: +# https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +# application: diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/application-tls.yml b/jhipster-5/bookstore-monolith/src/main/resources/config/application-tls.yml new file mode 100644 index 0000000000..c4e0565cc7 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/application-tls.yml @@ -0,0 +1,20 @@ +# =================================================================== +# Activate this profile to enable TLS and HTTP/2. +# +# JHipster has generated a self-signed certificate, which will be used to encrypt traffic. +# As your browser will not understand this certificate, you will need to import it. +# +# Another (easiest) solution with Chrome is to enable the "allow-insecure-localhost" flag +# at chrome://flags/#allow-insecure-localhost +# =================================================================== +server: + ssl: + key-store: classpath:config/tls/keystore.p12 + key-store-password: password + key-store-type: PKCS12 + key-alias: selfsigned + ciphers: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + enabled-protocols: TLSv1.2 +jhipster: + http: + version: V_2_0 diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/application.yml b/jhipster-5/bookstore-monolith/src/main/resources/config/application.yml new file mode 100644 index 0000000000..5b28b7f00d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/application.yml @@ -0,0 +1,140 @@ +# =================================================================== +# Spring Boot configuration. +# +# This configuration will be overridden by the Spring profile you use, +# for example application-dev.yml if you use the "dev" profile. +# +# More information on profiles: https://www.jhipster.tech/profiles/ +# More information on configuration properties: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +# =================================================================== +# Standard Spring Boot properties. +# Full reference is available at: +# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html +# =================================================================== + +management: + endpoints: + web: + base-path: /management + exposure: + include: ["configprops", "env", "health", "info", "threaddump", "logfile", "jhi-metrics", "prometheus" ] + endpoint: + health: + show-details: when-authorized + jhi-metrics: + enabled: true + info: + git: + mode: full + health: + mail: + enabled: false # When using the MailService, configure an SMTP server and set this to true + metrics: + export: + # Prometheus is the default metrics backend + prometheus: + enabled: true + step: 60 + binders: + jvm: + enabled: true + processor: + enabled: true + uptime: + enabled: true + logback: + enabled: true + files: + enabled: true + integration: + enabled: true + distribution: + percentiles-histogram: + all: true + percentiles: + all: 0, 0.5, 0.75, 0.95, 0.99, 1.0 + web: + server: + auto-time-requests: true + +spring: + application: + name: Bookstore + profiles: + # The commented value for `active` can be replaced with valid Spring profiles to load. + # Otherwise, it will be filled in by maven when building the WAR file + # Either way, it can be overridden by `--spring.profiles.active` value passed in the commandline or `-Dspring.profiles.active` set in `JAVA_OPTS` + active: #spring.profiles.active# + jpa: + open-in-view: false + properties: + hibernate.jdbc.time_zone: UTC + hibernate: + ddl-auto: none + naming: + physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy + implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy + messages: + basename: i18n/messages + mvc: + favicon: + enabled: false + thymeleaf: + mode: HTML + +server: + servlet: + session: + cookie: + http-only: true + +# Properties to be exposed on the /info management endpoint +info: + # Comma separated list of profiles that will trigger the ribbon to show + display-ribbon-on-profiles: "dev" + +# =================================================================== +# JHipster specific properties +# +# Full reference is available at: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +jhipster: + async: + core-pool-size: 2 + max-pool-size: 50 + queue-capacity: 10000 + # By default CORS is disabled. Uncomment to enable. + #cors: + #allowed-origins: "*" + #allowed-methods: "*" + #allowed-headers: "*" + #exposed-headers: "Authorization,Link,X-Total-Count" + #allow-credentials: true + #max-age: 1800 + mail: + from: Bookstore@localhost + swagger: + default-include-pattern: /api/.* + title: Bookstore API + description: Bookstore API documentation + version: 0.0.1 + terms-of-service-url: + contact-name: + contact-url: + contact-email: + license: + license-url: + +# =================================================================== +# Application specific properties +# Add your own application properties here, see the ApplicationProperties class +# to have type-safe configuration, like in the JHipsterProperties above +# +# More documentation is available at: +# https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +# application: diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/authorities.csv b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/authorities.csv new file mode 100644 index 0000000000..af5c6dfa18 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/authorities.csv @@ -0,0 +1,3 @@ +name +ROLE_ADMIN +ROLE_USER diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml new file mode 100644 index 0000000000..dd4b01d487 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/master.xml b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/master.xml new file mode 100644 index 0000000000..f2b0b1f7e6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/master.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/users.csv b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/users.csv new file mode 100644 index 0000000000..b25922b699 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/users.csv @@ -0,0 +1,5 @@ +id;login;password_hash;first_name;last_name;email;image_url;activated;lang_key;created_by;last_modified_by +1;system;$2a$10$mE.qmcV0mFU5NcKh73TZx.z4ueI/.bDWbj0T1BYyqP481kGGarKLG;System;System;system@localhost;;true;en;system;system +2;anonymoususer;$2a$10$j8S5d7Sr7.8VTOYNviDPOeWX8KcYILUVJBsYV83Y5NtECayypx9lO;Anonymous;User;anonymous@localhost;;true;en;system;system +3;admin;$2a$10$gSAhZrxMllrbgj/kkK9UceBPpChGWJA7SYIb1Mqo.n5aNLq1/oRrC;Administrator;Administrator;admin@localhost;;true;en;system;system +4;user;$2a$10$VEjxo0jq2YG9Rbk2HmX9S.k1uZBGYUHdUcid3g/vfiEl7lwWgOH/K;User;User;user@localhost;;true;en;system;system diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/users_authorities.csv b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/users_authorities.csv new file mode 100644 index 0000000000..06c5feeeea --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/users_authorities.csv @@ -0,0 +1,6 @@ +user_id;authority_name +1;ROLE_ADMIN +1;ROLE_USER +3;ROLE_ADMIN +3;ROLE_USER +4;ROLE_USER diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/tls/keystore.p12 b/jhipster-5/bookstore-monolith/src/main/resources/config/tls/keystore.p12 new file mode 100644 index 0000000000000000000000000000000000000000..364fad7435e01dddac14970a653b7a82c9e83089 GIT binary patch literal 2607 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 C+svr| literal 0 HcmV?d00001 diff --git a/jhipster-5/bookstore-monolith/src/main/resources/i18n/messages.properties b/jhipster-5/bookstore-monolith/src/main/resources/i18n/messages.properties new file mode 100644 index 0000000000..52a60093c5 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/i18n/messages.properties @@ -0,0 +1,21 @@ +# Error page +error.title=Your request cannot be processed +error.subtitle=Sorry, an error has occurred. +error.status=Status: +error.message=Message: + +# Activation email +email.activation.title=Bookstore account activation +email.activation.greeting=Dear {0} +email.activation.text1=Your Bookstore account has been created, please click on the URL below to activate it: +email.activation.text2=Regards, +email.signature=Bookstore Team. + +# Creation email +email.creation.text1=Your Bookstore account has been created, please click on the URL below to access it: + +# Reset email +email.reset.title=Bookstore password reset +email.reset.greeting=Dear {0} +email.reset.text1=For your Bookstore account a password reset was requested, please click on the URL below to reset it: +email.reset.text2=Regards, diff --git a/jhipster-5/bookstore-monolith/src/main/resources/logback-spring.xml b/jhipster-5/bookstore-monolith/src/main/resources/logback-spring.xml new file mode 100644 index 0000000000..4aa548af35 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/logback-spring.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + diff --git a/jhipster-5/bookstore-monolith/src/main/resources/templates/error.html b/jhipster-5/bookstore-monolith/src/main/resources/templates/error.html new file mode 100644 index 0000000000..08616bcf1e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/templates/error.html @@ -0,0 +1,163 @@ + + + + + + Your request cannot be processed + + + +

+

Your request cannot be processed :(

+ +

Sorry, an error has occurred.

+ + Status:  ()
+ + Message: 
+
+ + + +
+ + diff --git a/jhipster-5/bookstore-monolith/src/main/resources/templates/mail/activationEmail.html b/jhipster-5/bookstore-monolith/src/main/resources/templates/mail/activationEmail.html new file mode 100644 index 0000000000..cb021d8e6a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/templates/mail/activationEmail.html @@ -0,0 +1,25 @@ + + + + JHipster activation + + + + +

+ Dear +

+

+ Your JHipster account has been created, please click on the URL below to activate it: +

+

+ Activation link +

+

+ Regards, +
+ JHipster. +

+ + diff --git a/jhipster-5/bookstore-monolith/src/main/resources/templates/mail/creationEmail.html b/jhipster-5/bookstore-monolith/src/main/resources/templates/mail/creationEmail.html new file mode 100644 index 0000000000..dc0cff5883 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/templates/mail/creationEmail.html @@ -0,0 +1,25 @@ + + + + JHipster creation + + + + +

+ Dear +

+

+ Your JHipster account has been created, please click on the URL below to access it: +

+

+ Login link +

+

+ Regards, +
+ JHipster. +

+ + diff --git a/jhipster-5/bookstore-monolith/src/main/resources/templates/mail/passwordResetEmail.html b/jhipster-5/bookstore-monolith/src/main/resources/templates/mail/passwordResetEmail.html new file mode 100644 index 0000000000..f44511265b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/templates/mail/passwordResetEmail.html @@ -0,0 +1,25 @@ + + + + JHipster password reset + + + + +

+ Dear +

+

+ For your JHipster account a password reset was requested, please click on the URL below to reset it: +

+

+ Login link +

+

+ Regards, +
+ JHipster. +

+ + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/404.html b/jhipster-5/bookstore-monolith/src/main/webapp/404.html new file mode 100644 index 0000000000..3fdc0bee1a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/404.html @@ -0,0 +1,61 @@ + + + + + Page Not Found + + + + + +

Page Not Found

+

Sorry, but the page you were trying to view does not exist.

+ + + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/account.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/account.module.ts new file mode 100644 index 0000000000..a167cab1c2 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/account.module.ts @@ -0,0 +1,30 @@ +import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { BookstoreSharedModule } from 'app/shared'; + +import { + PasswordStrengthBarComponent, + RegisterComponent, + ActivateComponent, + PasswordComponent, + PasswordResetInitComponent, + PasswordResetFinishComponent, + SettingsComponent, + accountState +} from './'; + +@NgModule({ + imports: [BookstoreSharedModule, RouterModule.forChild(accountState)], + declarations: [ + ActivateComponent, + RegisterComponent, + PasswordComponent, + PasswordStrengthBarComponent, + PasswordResetInitComponent, + PasswordResetFinishComponent, + SettingsComponent + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BookstoreAccountModule {} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/account.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/account.route.ts new file mode 100644 index 0000000000..f849342e69 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/account.route.ts @@ -0,0 +1,12 @@ +import { Routes } from '@angular/router'; + +import { activateRoute, passwordRoute, passwordResetFinishRoute, passwordResetInitRoute, registerRoute, settingsRoute } from './'; + +const ACCOUNT_ROUTES = [activateRoute, passwordRoute, passwordResetFinishRoute, passwordResetInitRoute, registerRoute, settingsRoute]; + +export const accountState: Routes = [ + { + path: '', + children: ACCOUNT_ROUTES + } +]; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.component.html new file mode 100644 index 0000000000..c7078ede86 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.component.html @@ -0,0 +1,17 @@ +
+
+
+

Activation

+ +
+ Your user account has been activated. Please + sign in. +
+ +
+ Your user could not be activated. Please use the registration form to sign up. +
+ +
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.component.ts new file mode 100644 index 0000000000..5c398073c3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.component.ts @@ -0,0 +1,37 @@ +import { Component, OnInit } from '@angular/core'; +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute } from '@angular/router'; + +import { LoginModalService } from 'app/core'; +import { ActivateService } from './activate.service'; + +@Component({ + selector: 'jhi-activate', + templateUrl: './activate.component.html' +}) +export class ActivateComponent implements OnInit { + error: string; + success: string; + modalRef: NgbModalRef; + + constructor(private activateService: ActivateService, private loginModalService: LoginModalService, private route: ActivatedRoute) {} + + ngOnInit() { + this.route.queryParams.subscribe(params => { + this.activateService.get(params['key']).subscribe( + () => { + this.error = null; + this.success = 'OK'; + }, + () => { + this.success = null; + this.error = 'ERROR'; + } + ); + }); + } + + login() { + this.modalRef = this.loginModalService.open(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.route.ts new file mode 100644 index 0000000000..b415b17a18 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.route.ts @@ -0,0 +1,12 @@ +import { Route } from '@angular/router'; + +import { ActivateComponent } from './activate.component'; + +export const activateRoute: Route = { + path: 'activate', + component: ActivateComponent, + data: { + authorities: [], + pageTitle: 'Activation' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.service.ts new file mode 100644 index 0000000000..adade9efad --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/activate/activate.service.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpParams } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable({ providedIn: 'root' }) +export class ActivateService { + constructor(private http: HttpClient) {} + + get(key: string): Observable { + return this.http.get(SERVER_API_URL + 'api/activate', { + params: new HttpParams().set('key', key) + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/index.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/index.ts new file mode 100644 index 0000000000..aeada0551c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/index.ts @@ -0,0 +1,19 @@ +export * from './activate/activate.component'; +export * from './activate/activate.service'; +export * from './activate/activate.route'; +export * from './password/password.component'; +export * from './password/password-strength-bar.component'; +export * from './password/password.service'; +export * from './password/password.route'; +export * from './password-reset/finish/password-reset-finish.component'; +export * from './password-reset/finish/password-reset-finish.service'; +export * from './password-reset/finish/password-reset-finish.route'; +export * from './password-reset/init/password-reset-init.component'; +export * from './password-reset/init/password-reset-init.service'; +export * from './password-reset/init/password-reset-init.route'; +export * from './register/register.component'; +export * from './register/register.service'; +export * from './register/register.route'; +export * from './settings/settings.component'; +export * from './settings/settings.route'; +export * from './account.route'; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.html new file mode 100644 index 0000000000..6d6baea694 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.html @@ -0,0 +1,77 @@ +
+
+
+

Reset password

+ +
+ The password reset key is missing. +
+ +
+

Choose a new password

+
+ +
+

Your password couldn't be reset. Remember a password request is only valid for 24 hours.

+
+ +

+ Your password has been reset. Please + sign in. +

+ +
+ The password and its confirmation do not match! +
+ +
+
+
+ + +
+ + Your password is required. + + + Your password is required to be at least 4 characters. + + + Your password cannot be longer than 50 characters. + +
+ +
+ +
+ + +
+ + Your password confirmation is required. + + + Your password confirmation is required to be at least 4 characters. + + + Your password confirmation cannot be longer than 50 characters. + +
+
+ +
+
+ +
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.ts new file mode 100644 index 0000000000..72aac25c96 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.ts @@ -0,0 +1,65 @@ +import { Component, OnInit, AfterViewInit, Renderer, ElementRef } from '@angular/core'; +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { ActivatedRoute } from '@angular/router'; + +import { LoginModalService } from 'app/core'; +import { PasswordResetFinishService } from './password-reset-finish.service'; + +@Component({ + selector: 'jhi-password-reset-finish', + templateUrl: './password-reset-finish.component.html' +}) +export class PasswordResetFinishComponent implements OnInit, AfterViewInit { + confirmPassword: string; + doNotMatch: string; + error: string; + keyMissing: boolean; + resetAccount: any; + success: string; + modalRef: NgbModalRef; + key: string; + + constructor( + private passwordResetFinishService: PasswordResetFinishService, + private loginModalService: LoginModalService, + private route: ActivatedRoute, + private elementRef: ElementRef, + private renderer: Renderer + ) {} + + ngOnInit() { + this.route.queryParams.subscribe(params => { + this.key = params['key']; + }); + this.resetAccount = {}; + this.keyMissing = !this.key; + } + + ngAfterViewInit() { + if (this.elementRef.nativeElement.querySelector('#password') != null) { + this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#password'), 'focus', []); + } + } + + finishReset() { + this.doNotMatch = null; + this.error = null; + if (this.resetAccount.password !== this.confirmPassword) { + this.doNotMatch = 'ERROR'; + } else { + this.passwordResetFinishService.save({ key: this.key, newPassword: this.resetAccount.password }).subscribe( + () => { + this.success = 'OK'; + }, + () => { + this.success = null; + this.error = 'ERROR'; + } + ); + } + } + + login() { + this.modalRef = this.loginModalService.open(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.route.ts new file mode 100644 index 0000000000..a09cba9377 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.route.ts @@ -0,0 +1,12 @@ +import { Route } from '@angular/router'; + +import { PasswordResetFinishComponent } from './password-reset-finish.component'; + +export const passwordResetFinishRoute: Route = { + path: 'reset/finish', + component: PasswordResetFinishComponent, + data: { + authorities: [], + pageTitle: 'Password' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.service.ts new file mode 100644 index 0000000000..706bdaa5b1 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/finish/password-reset-finish.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable({ providedIn: 'root' }) +export class PasswordResetFinishService { + constructor(private http: HttpClient) {} + + save(keyAndPassword: any): Observable { + return this.http.post(SERVER_API_URL + 'api/account/reset-password/finish', keyAndPassword); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.component.html new file mode 100644 index 0000000000..7fe7b0bdec --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.component.html @@ -0,0 +1,46 @@ +
+
+
+

Reset your password

+ +
+ Email address isn't registered! Please check and try again. +
+ +
+

Enter the email address you used to register.

+
+ +
+

Check your emails for details on how to reset your password.

+
+ +
+
+ + +
+ + Your email is required. + + + Your email is invalid. + + + Your email is required to be at least 5 characters. + + + Your email cannot be longer than 100 characters. + +
+
+ +
+
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.component.ts new file mode 100644 index 0000000000..e32617341c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.component.ts @@ -0,0 +1,43 @@ +import { Component, OnInit, AfterViewInit, Renderer, ElementRef } from '@angular/core'; +import { EMAIL_NOT_FOUND_TYPE } from 'app/shared'; +import { PasswordResetInitService } from './password-reset-init.service'; + +@Component({ + selector: 'jhi-password-reset-init', + templateUrl: './password-reset-init.component.html' +}) +export class PasswordResetInitComponent implements OnInit, AfterViewInit { + error: string; + errorEmailNotExists: string; + resetAccount: any; + success: string; + + constructor(private passwordResetInitService: PasswordResetInitService, private elementRef: ElementRef, private renderer: Renderer) {} + + ngOnInit() { + this.resetAccount = {}; + } + + ngAfterViewInit() { + this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#email'), 'focus', []); + } + + requestReset() { + this.error = null; + this.errorEmailNotExists = null; + + this.passwordResetInitService.save(this.resetAccount.email).subscribe( + () => { + this.success = 'OK'; + }, + response => { + this.success = null; + if (response.status === 400 && response.error.type === EMAIL_NOT_FOUND_TYPE) { + this.errorEmailNotExists = 'ERROR'; + } else { + this.error = 'ERROR'; + } + } + ); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.route.ts new file mode 100644 index 0000000000..a1708c98b3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.route.ts @@ -0,0 +1,12 @@ +import { Route } from '@angular/router'; + +import { PasswordResetInitComponent } from './password-reset-init.component'; + +export const passwordResetInitRoute: Route = { + path: 'reset/request', + component: PasswordResetInitComponent, + data: { + authorities: [], + pageTitle: 'Password' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.service.ts new file mode 100644 index 0000000000..c24ccf94d2 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password-reset/init/password-reset-init.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable({ providedIn: 'root' }) +export class PasswordResetInitService { + constructor(private http: HttpClient) {} + + save(mail: string): Observable { + return this.http.post(SERVER_API_URL + 'api/account/reset-password/init', mail); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password-strength-bar.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password-strength-bar.component.ts new file mode 100644 index 0000000000..4159fde882 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password-strength-bar.component.ts @@ -0,0 +1,85 @@ +import { Component, ElementRef, Input, Renderer } from '@angular/core'; + +@Component({ + selector: 'jhi-password-strength-bar', + template: ` +
+ Password strength: +
    +
  • +
  • +
  • +
  • +
  • +
+
+ `, + styleUrls: ['password-strength-bar.scss'] +}) +export class PasswordStrengthBarComponent { + colors = ['#F00', '#F90', '#FF0', '#9F0', '#0F0']; + + constructor(private renderer: Renderer, private elementRef: ElementRef) {} + + measureStrength(p: string): number { + let force = 0; + const regex = /[$-/:-?{-~!"^_`\[\]]/g; // " + const lowerLetters = /[a-z]+/.test(p); + const upperLetters = /[A-Z]+/.test(p); + const numbers = /[0-9]+/.test(p); + const symbols = regex.test(p); + + const flags = [lowerLetters, upperLetters, numbers, symbols]; + const passedMatches = flags.filter((isMatchedFlag: boolean) => { + return isMatchedFlag === true; + }).length; + + force += 2 * p.length + (p.length >= 10 ? 1 : 0); + force += passedMatches * 10; + + // penalty (short password) + force = p.length <= 6 ? Math.min(force, 10) : force; + + // penalty (poor variety of characters) + force = passedMatches === 1 ? Math.min(force, 10) : force; + force = passedMatches === 2 ? Math.min(force, 20) : force; + force = passedMatches === 3 ? Math.min(force, 40) : force; + + return force; + } + + getColor(s: number): any { + let idx = 0; + if (s <= 10) { + idx = 0; + } else if (s <= 20) { + idx = 1; + } else if (s <= 30) { + idx = 2; + } else if (s <= 40) { + idx = 3; + } else { + idx = 4; + } + return { idx: idx + 1, col: this.colors[idx] }; + } + + @Input() + set passwordToCheck(password: string) { + if (password) { + const c = this.getColor(this.measureStrength(password)); + const element = this.elementRef.nativeElement; + if (element.className) { + this.renderer.setElementClass(element, element.className, false); + } + const lis = element.getElementsByTagName('li'); + for (let i = 0; i < lis.length; i++) { + if (i < c.idx) { + this.renderer.setElementStyle(lis[i], 'backgroundColor', c.col); + } else { + this.renderer.setElementStyle(lis[i], 'backgroundColor', '#DDD'); + } + } + } + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password-strength-bar.scss b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password-strength-bar.scss new file mode 100644 index 0000000000..9744b9b784 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password-strength-bar.scss @@ -0,0 +1,23 @@ +/* ========================================================================== +start Password strength bar style +========================================================================== */ +ul#strength { + display: inline; + list-style: none; + margin: 0; + margin-left: 15px; + padding: 0; + vertical-align: 2px; +} + +.point { + background: #ddd; + border-radius: 2px; + display: inline-block; + height: 5px; + margin-right: 1px; + width: 20px; + &:last-child { + margin: 0 !important; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.component.html new file mode 100644 index 0000000000..79fb60c3bc --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.component.html @@ -0,0 +1,77 @@ +
+
+
+

Password for [{{account.login}}]

+ +
+ Password changed! +
+
+ An error has occurred! The password could not be changed. +
+ +
+ The password and its confirmation do not match! +
+ +
+ +
+ + +
+ + Your password is required. + +
+
+
+ + +
+ + Your password is required. + + + Your password is required to be at least 4 characters. + + + Your password cannot be longer than 50 characters. + +
+ +
+
+ + +
+ + Your confirmation password is required. + + + Your confirmation password is required to be at least 4 characters. + + + Your confirmation password cannot be longer than 50 characters. + +
+
+ + +
+
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.component.ts new file mode 100644 index 0000000000..3004effa57 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.component.ts @@ -0,0 +1,46 @@ +import { Component, OnInit } from '@angular/core'; + +import { AccountService } from 'app/core'; +import { PasswordService } from './password.service'; + +@Component({ + selector: 'jhi-password', + templateUrl: './password.component.html' +}) +export class PasswordComponent implements OnInit { + doNotMatch: string; + error: string; + success: string; + account: any; + currentPassword: string; + newPassword: string; + confirmPassword: string; + + constructor(private passwordService: PasswordService, private accountService: AccountService) {} + + ngOnInit() { + this.accountService.identity().then(account => { + this.account = account; + }); + } + + changePassword() { + if (this.newPassword !== this.confirmPassword) { + this.error = null; + this.success = null; + this.doNotMatch = 'ERROR'; + } else { + this.doNotMatch = null; + this.passwordService.save(this.newPassword, this.currentPassword).subscribe( + () => { + this.error = null; + this.success = 'OK'; + }, + () => { + this.success = null; + this.error = 'ERROR'; + } + ); + } + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.route.ts new file mode 100644 index 0000000000..4bb115fd44 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.route.ts @@ -0,0 +1,14 @@ +import { Route } from '@angular/router'; + +import { UserRouteAccessService } from 'app/core'; +import { PasswordComponent } from './password.component'; + +export const passwordRoute: Route = { + path: 'password', + component: PasswordComponent, + data: { + authorities: ['ROLE_USER'], + pageTitle: 'Password' + }, + canActivate: [UserRouteAccessService] +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.service.ts new file mode 100644 index 0000000000..028df7b0e4 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/password/password.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable({ providedIn: 'root' }) +export class PasswordService { + constructor(private http: HttpClient) {} + + save(newPassword: string, currentPassword: string): Observable { + return this.http.post(SERVER_API_URL + 'api/account/change-password', { currentPassword, newPassword }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.component.html new file mode 100644 index 0000000000..596f782828 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.component.html @@ -0,0 +1,124 @@ +
+
+
+

Registration

+ +
+ Registration saved! Please check your email for confirmation. +
+ +
+ Registration failed! Please try again later. +
+ +
+ Login name already registered! Please choose another one. +
+ +
+ Email is already in use! Please choose another one. +
+ +
+ The password and its confirmation do not match! +
+
+
+
+
+
+
+ + +
+ + Your username is required. + + + Your username is required to be at least 1 character. + + + Your username cannot be longer than 50 characters. + + + Your username can only contain letters and digits. + +
+
+
+ + +
+ + Your email is required. + + + Your email is invalid. + + + Your email is required to be at least 5 characters. + + + Your email cannot be longer than 100 characters. + +
+
+
+ + +
+ + Your password is required. + + + Your password is required to be at least 4 characters. + + + Your password cannot be longer than 50 characters. + +
+ +
+
+ + +
+ + Your confirmation password is required. + + + Your confirmation password is required to be at least 4 characters. + + + Your confirmation password cannot be longer than 50 characters. + +
+
+ + +
+

+
+ If you want to + sign in, you can try the default accounts:
- Administrator (login="admin" and password="admin")
- User (login="user" and password="user").
+
+
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.component.ts new file mode 100644 index 0000000000..85244d2970 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.component.ts @@ -0,0 +1,71 @@ +import { Component, OnInit, AfterViewInit, Renderer, ElementRef } from '@angular/core'; +import { HttpErrorResponse } from '@angular/common/http'; +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; + +import { EMAIL_ALREADY_USED_TYPE, LOGIN_ALREADY_USED_TYPE } from 'app/shared'; +import { LoginModalService } from 'app/core'; +import { Register } from './register.service'; + +@Component({ + selector: 'jhi-register', + templateUrl: './register.component.html' +}) +export class RegisterComponent implements OnInit, AfterViewInit { + confirmPassword: string; + doNotMatch: string; + error: string; + errorEmailExists: string; + errorUserExists: string; + registerAccount: any; + success: boolean; + modalRef: NgbModalRef; + + constructor( + private loginModalService: LoginModalService, + private registerService: Register, + private elementRef: ElementRef, + private renderer: Renderer + ) {} + + ngOnInit() { + this.success = false; + this.registerAccount = {}; + } + + ngAfterViewInit() { + this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#login'), 'focus', []); + } + + register() { + if (this.registerAccount.password !== this.confirmPassword) { + this.doNotMatch = 'ERROR'; + } else { + this.doNotMatch = null; + this.error = null; + this.errorUserExists = null; + this.errorEmailExists = null; + this.registerAccount.langKey = 'en'; + this.registerService.save(this.registerAccount).subscribe( + () => { + this.success = true; + }, + response => this.processError(response) + ); + } + } + + openLogin() { + this.modalRef = this.loginModalService.open(); + } + + private processError(response: HttpErrorResponse) { + this.success = null; + if (response.status === 400 && response.error.type === LOGIN_ALREADY_USED_TYPE) { + this.errorUserExists = 'ERROR'; + } else if (response.status === 400 && response.error.type === EMAIL_ALREADY_USED_TYPE) { + this.errorEmailExists = 'ERROR'; + } else { + this.error = 'ERROR'; + } + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.route.ts new file mode 100644 index 0000000000..626cd32ff9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.route.ts @@ -0,0 +1,12 @@ +import { Route } from '@angular/router'; + +import { RegisterComponent } from './register.component'; + +export const registerRoute: Route = { + path: 'register', + component: RegisterComponent, + data: { + authorities: [], + pageTitle: 'Registration' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.service.ts new file mode 100644 index 0000000000..dfe6f1da6a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/register/register.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable({ providedIn: 'root' }) +export class Register { + constructor(private http: HttpClient) {} + + save(account: any): Observable { + return this.http.post(SERVER_API_URL + 'api/register', account); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.component.html new file mode 100644 index 0000000000..bae1bb67e6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.component.html @@ -0,0 +1,80 @@ +
+
+
+

User settings for [{{settingsAccount.login}}]

+ +
+ Settings saved! +
+ + + +
+ +
+ + +
+ + Your first name is required. + + + Your first name is required to be at least 1 character. + + + Your first name cannot be longer than 50 characters. + +
+
+
+ + +
+ + Your last name is required. + + + Your last name is required to be at least 1 character. + + + Your last name cannot be longer than 50 characters. + +
+
+
+ + +
+ + Your email is required. + + + Your email is invalid. + + + Your email is required to be at least 5 characters. + + + Your email cannot be longer than 100 characters. + +
+
+ +
+
+
+ +
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.component.ts new file mode 100644 index 0000000000..92afaca793 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.component.ts @@ -0,0 +1,50 @@ +import { Component, OnInit } from '@angular/core'; + +import { AccountService } from 'app/core'; + +@Component({ + selector: 'jhi-settings', + templateUrl: './settings.component.html' +}) +export class SettingsComponent implements OnInit { + error: string; + success: string; + settingsAccount: any; + languages: any[]; + + constructor(private accountService: AccountService) {} + + ngOnInit() { + this.accountService.identity().then(account => { + this.settingsAccount = this.copyAccount(account); + }); + } + + save() { + this.accountService.save(this.settingsAccount).subscribe( + () => { + this.error = null; + this.success = 'OK'; + this.accountService.identity(true).then(account => { + this.settingsAccount = this.copyAccount(account); + }); + }, + () => { + this.success = null; + this.error = 'ERROR'; + } + ); + } + + copyAccount(account) { + return { + activated: account.activated, + email: account.email, + firstName: account.firstName, + langKey: account.langKey, + lastName: account.lastName, + login: account.login, + imageUrl: account.imageUrl + }; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.route.ts new file mode 100644 index 0000000000..3c9cf18e15 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/account/settings/settings.route.ts @@ -0,0 +1,14 @@ +import { Route } from '@angular/router'; + +import { UserRouteAccessService } from 'app/core'; +import { SettingsComponent } from './settings.component'; + +export const settingsRoute: Route = { + path: 'settings', + component: SettingsComponent, + data: { + authorities: ['ROLE_USER'], + pageTitle: 'Settings' + }, + canActivate: [UserRouteAccessService] +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/admin.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/admin.module.ts new file mode 100644 index 0000000000..4e46e0fe13 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/admin.module.ts @@ -0,0 +1,43 @@ +import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { BookstoreSharedModule } from 'app/shared'; +/* jhipster-needle-add-admin-module-import - JHipster will add admin modules imports here */ + +import { + adminState, + AuditsComponent, + UserMgmtComponent, + UserMgmtDetailComponent, + UserMgmtUpdateComponent, + UserMgmtDeleteDialogComponent, + LogsComponent, + JhiMetricsMonitoringComponent, + JhiHealthModalComponent, + JhiHealthCheckComponent, + JhiConfigurationComponent, + JhiDocsComponent +} from './'; + +@NgModule({ + imports: [ + BookstoreSharedModule, + RouterModule.forChild(adminState) + /* jhipster-needle-add-admin-module - JHipster will add admin modules here */ + ], + declarations: [ + AuditsComponent, + UserMgmtComponent, + UserMgmtDetailComponent, + UserMgmtUpdateComponent, + UserMgmtDeleteDialogComponent, + LogsComponent, + JhiConfigurationComponent, + JhiHealthCheckComponent, + JhiHealthModalComponent, + JhiDocsComponent, + JhiMetricsMonitoringComponent + ], + entryComponents: [UserMgmtDeleteDialogComponent, JhiHealthModalComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BookstoreAdminModule {} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/admin.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/admin.route.ts new file mode 100644 index 0000000000..88c7e575f0 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/admin.route.ts @@ -0,0 +1,18 @@ +import { Routes } from '@angular/router'; + +import { auditsRoute, configurationRoute, docsRoute, healthRoute, logsRoute, metricsRoute, userMgmtRoute } from './'; + +import { UserRouteAccessService } from 'app/core'; + +const ADMIN_ROUTES = [auditsRoute, configurationRoute, docsRoute, healthRoute, logsRoute, ...userMgmtRoute, metricsRoute]; + +export const adminState: Routes = [ + { + path: '', + data: { + authorities: ['ROLE_ADMIN'] + }, + canActivate: [UserRouteAccessService], + children: ADMIN_ROUTES + } +]; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audit-data.model.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audit-data.model.ts new file mode 100644 index 0000000000..a2506c4090 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audit-data.model.ts @@ -0,0 +1,3 @@ +export class AuditData { + constructor(public remoteAddress: string, public sessionId: string) {} +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audit.model.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audit.model.ts new file mode 100644 index 0000000000..6497fb444e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audit.model.ts @@ -0,0 +1,5 @@ +import { AuditData } from './audit-data.model'; + +export class Audit { + constructor(public data: AuditData, public principal: string, public timestamp: string, public type: string) {} +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.component.html new file mode 100644 index 0000000000..38af44044a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.component.html @@ -0,0 +1,52 @@ +
+

Audits

+ +
+
+

Filter by date

+
+
+ from +
+ + +
+ To +
+ +
+
+
+ +
+ + + + + + + + + + + + + + + + + +
DateUserStateExtra data
{{audit.timestamp| date:'medium'}}{{audit.principal}}{{audit.type}} + {{audit.data.message}} + Remote Address {{audit.data.remoteAddress}} +
+
+
+
+ +
+
+ +
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.component.ts new file mode 100644 index 0000000000..21739275f2 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.component.ts @@ -0,0 +1,126 @@ +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { HttpResponse } from '@angular/common/http'; +import { DatePipe } from '@angular/common'; +import { ActivatedRoute, Router } from '@angular/router'; +import { JhiParseLinks, JhiAlertService } from 'ng-jhipster'; + +import { ITEMS_PER_PAGE } from 'app/shared'; +import { Audit } from './audit.model'; +import { AuditsService } from './audits.service'; + +@Component({ + selector: 'jhi-audit', + templateUrl: './audits.component.html' +}) +export class AuditsComponent implements OnInit, OnDestroy { + audits: Audit[]; + fromDate: string; + itemsPerPage: any; + links: any; + page: number; + routeData: any; + predicate: any; + previousPage: any; + reverse: boolean; + toDate: string; + totalItems: number; + + constructor( + private auditsService: AuditsService, + private alertService: JhiAlertService, + private parseLinks: JhiParseLinks, + private activatedRoute: ActivatedRoute, + private datePipe: DatePipe, + private router: Router + ) { + this.itemsPerPage = ITEMS_PER_PAGE; + this.routeData = this.activatedRoute.data.subscribe(data => { + this.page = data['pagingParams'].page; + this.previousPage = data['pagingParams'].page; + this.reverse = data['pagingParams'].ascending; + this.predicate = data['pagingParams'].predicate; + }); + } + + ngOnInit() { + this.today(); + this.previousMonth(); + this.loadAll(); + } + + ngOnDestroy() { + this.routeData.unsubscribe(); + } + + previousMonth() { + const dateFormat = 'yyyy-MM-dd'; + let fromDate: Date = new Date(); + + if (fromDate.getMonth() === 0) { + fromDate = new Date(fromDate.getFullYear() - 1, 11, fromDate.getDate()); + } else { + fromDate = new Date(fromDate.getFullYear(), fromDate.getMonth() - 1, fromDate.getDate()); + } + + this.fromDate = this.datePipe.transform(fromDate, dateFormat); + } + + today() { + const dateFormat = 'yyyy-MM-dd'; + // Today + 1 day - needed if the current day must be included + const today: Date = new Date(); + today.setDate(today.getDate() + 1); + const date = new Date(today.getFullYear(), today.getMonth(), today.getDate()); + this.toDate = this.datePipe.transform(date, dateFormat); + } + + loadAll() { + this.auditsService + .query({ + page: this.page - 1, + size: this.itemsPerPage, + sort: this.sort(), + fromDate: this.fromDate, + toDate: this.toDate + }) + .subscribe( + (res: HttpResponse) => this.onSuccess(res.body, res.headers), + (res: HttpResponse) => this.onError(res.body) + ); + } + + sort() { + const result = [this.predicate + ',' + (this.reverse ? 'asc' : 'desc')]; + if (this.predicate !== 'id') { + result.push('id'); + } + return result; + } + + loadPage(page: number) { + if (page !== this.previousPage) { + this.previousPage = page; + this.transition(); + } + } + + transition() { + this.router.navigate(['/admin/audits'], { + queryParams: { + page: this.page, + sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc') + } + }); + this.loadAll(); + } + + private onSuccess(data, headers) { + this.links = this.parseLinks.parse(headers.get('link')); + this.totalItems = headers.get('X-Total-Count'); + this.audits = data; + } + + private onError(error) { + this.alertService.error(error.error, error.message, null); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.route.ts new file mode 100644 index 0000000000..87af5c6e8c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.route.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Route } from '@angular/router'; +import { JhiPaginationUtil, JhiResolvePagingParams } from 'ng-jhipster'; + +import { AuditsComponent } from './audits.component'; + +export const auditsRoute: Route = { + path: 'audits', + component: AuditsComponent, + resolve: { + pagingParams: JhiResolvePagingParams + }, + data: { + pageTitle: 'Audits', + defaultSort: 'auditEventDate,desc' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.service.ts new file mode 100644 index 0000000000..78e8cca7e2 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/audits/audits.service.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { createRequestOption } from 'app/shared'; +import { SERVER_API_URL } from 'app/app.constants'; +import { Audit } from './audit.model'; + +@Injectable({ providedIn: 'root' }) +export class AuditsService { + constructor(private http: HttpClient) {} + + query(req: any): Observable> { + const params: HttpParams = createRequestOption(req); + params.set('fromDate', req.fromDate); + params.set('toDate', req.toDate); + + const requestURL = SERVER_API_URL + 'management/audits'; + + return this.http.get(requestURL, { + params, + observe: 'response' + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.component.html new file mode 100644 index 0000000000..02a4a96433 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.component.html @@ -0,0 +1,46 @@ +
+

Configuration

+ + Filter (by prefix) +

Spring configuration

+ + + + + + + + + + + + + +
PrefixProperties
{{entry.prefix}} +
+
{{key}}
+
+ {{entry.properties[key] | json}} +
+
+
+
+

{{key}}

+ + + + + + + + + + + + + +
PropertyValue
{{item.key}} + {{item.val}} +
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.component.ts new file mode 100644 index 0000000000..6867210c91 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.component.ts @@ -0,0 +1,43 @@ +import { Component, OnInit } from '@angular/core'; + +import { JhiConfigurationService } from './configuration.service'; + +@Component({ + selector: 'jhi-configuration', + templateUrl: './configuration.component.html' +}) +export class JhiConfigurationComponent implements OnInit { + allConfiguration: any = null; + configuration: any = null; + configKeys: any[]; + filter: string; + orderProp: string; + reverse: boolean; + + constructor(private configurationService: JhiConfigurationService) { + this.configKeys = []; + this.filter = ''; + this.orderProp = 'prefix'; + this.reverse = false; + } + + keys(dict): Array { + return dict === undefined ? [] : Object.keys(dict); + } + + ngOnInit() { + this.configurationService.get().subscribe(configuration => { + this.configuration = configuration; + + for (const config of configuration) { + if (config.properties !== undefined) { + this.configKeys.push(Object.keys(config.properties)); + } + } + }); + + this.configurationService.getEnv().subscribe(configuration => { + this.allConfiguration = configuration; + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.route.ts new file mode 100644 index 0000000000..f4ad9c3688 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.route.ts @@ -0,0 +1,11 @@ +import { Route } from '@angular/router'; + +import { JhiConfigurationComponent } from './configuration.component'; + +export const configurationRoute: Route = { + path: 'jhi-configuration', + component: JhiConfigurationComponent, + data: { + pageTitle: 'Configuration' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.service.ts new file mode 100644 index 0000000000..5f9dfd491c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/configuration/configuration.service.ts @@ -0,0 +1,67 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable({ providedIn: 'root' }) +export class JhiConfigurationService { + constructor(private http: HttpClient) {} + + get(): Observable { + return this.http.get(SERVER_API_URL + 'management/configprops', { observe: 'response' }).pipe( + map((res: HttpResponse) => { + const properties: any[] = []; + const propertiesObject = this.getConfigPropertiesObjects(res.body); + for (const key in propertiesObject) { + if (propertiesObject.hasOwnProperty(key)) { + properties.push(propertiesObject[key]); + } + } + + return properties.sort((propertyA, propertyB) => { + return propertyA.prefix === propertyB.prefix ? 0 : propertyA.prefix < propertyB.prefix ? -1 : 1; + }); + }) + ); + } + + getConfigPropertiesObjects(res: Object) { + // This code is for Spring Boot 2 + if (res['contexts'] !== undefined) { + for (const key in res['contexts']) { + // If the key is not bootstrap, it will be the ApplicationContext Id + // For default app, it is baseName + // For microservice, it is baseName-1 + if (!key.startsWith('bootstrap')) { + return res['contexts'][key]['beans']; + } + } + } + // by default, use the default ApplicationContext Id + return res['contexts']['Bookstore']['beans']; + } + + getEnv(): Observable { + return this.http.get(SERVER_API_URL + 'management/env', { observe: 'response' }).pipe( + map((res: HttpResponse) => { + const properties: any = {}; + const propertySources = res.body['propertySources']; + + for (const propertyObject of propertySources) { + const name = propertyObject['name']; + const detailProperties = propertyObject['properties']; + const vals: any[] = []; + for (const keyDetail in detailProperties) { + if (detailProperties.hasOwnProperty(keyDetail)) { + vals.push({ key: keyDetail, val: detailProperties[keyDetail]['value'] }); + } + } + properties[name] = vals; + } + return properties; + }) + ); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.component.html new file mode 100644 index 0000000000..30efbbb93e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.component.html @@ -0,0 +1,2 @@ + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.component.ts new file mode 100644 index 0000000000..b338e7c3a6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.component.ts @@ -0,0 +1,9 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'jhi-docs', + templateUrl: './docs.component.html' +}) +export class JhiDocsComponent { + constructor() {} +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.route.ts new file mode 100644 index 0000000000..d7df51b935 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/docs/docs.route.ts @@ -0,0 +1,11 @@ +import { Route } from '@angular/router'; + +import { JhiDocsComponent } from './docs.component'; + +export const docsRoute: Route = { + path: 'docs', + component: JhiDocsComponent, + data: { + pageTitle: 'API' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health-modal.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health-modal.component.html new file mode 100644 index 0000000000..efc125e3a0 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health-modal.component.html @@ -0,0 +1,35 @@ + + + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health-modal.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health-modal.component.ts new file mode 100644 index 0000000000..28128bf321 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health-modal.component.ts @@ -0,0 +1,41 @@ +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; + +import { JhiHealthService } from './health.service'; + +@Component({ + selector: 'jhi-health-modal', + templateUrl: './health-modal.component.html' +}) +export class JhiHealthModalComponent { + currentHealth: any; + + constructor(private healthService: JhiHealthService, public activeModal: NgbActiveModal) {} + + baseName(name) { + return this.healthService.getBaseName(name); + } + + subSystemName(name) { + return this.healthService.getSubSystemName(name); + } + + readableValue(value: number) { + if (this.currentHealth.name === 'diskSpace') { + // Should display storage space in an human readable unit + const val = value / 1073741824; + if (val > 1) { + // Value + return val.toFixed(2) + ' GB'; + } else { + return (value / 1048576).toFixed(2) + ' MB'; + } + } + + if (typeof value === 'object') { + return JSON.stringify(value); + } else { + return value.toString(); + } + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.component.html new file mode 100644 index 0000000000..b314daa0ba --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.component.html @@ -0,0 +1,34 @@ +
+

+ Health Checks + +

+
+ + + + + + + + + + + + + + + +
Service NameStatusDetails
{{ baseName(health.name) }} {{subSystemName(health.name)}} + + {{health.status}} + + + + + +
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.component.ts new file mode 100644 index 0000000000..ada3ef62f4 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.component.ts @@ -0,0 +1,66 @@ +import { Component, OnInit } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; + +import { JhiHealthService } from './health.service'; +import { JhiHealthModalComponent } from './health-modal.component'; + +@Component({ + selector: 'jhi-health', + templateUrl: './health.component.html' +}) +export class JhiHealthCheckComponent implements OnInit { + healthData: any; + updatingHealth: boolean; + + constructor(private modalService: NgbModal, private healthService: JhiHealthService) {} + + ngOnInit() { + this.refresh(); + } + + baseName(name: string) { + return this.healthService.getBaseName(name); + } + + getBadgeClass(statusState) { + if (statusState === 'UP') { + return 'badge-success'; + } else { + return 'badge-danger'; + } + } + + refresh() { + this.updatingHealth = true; + + this.healthService.checkHealth().subscribe( + health => { + this.healthData = this.healthService.transformHealthData(health); + this.updatingHealth = false; + }, + error => { + if (error.status === 503) { + this.healthData = this.healthService.transformHealthData(error.error); + this.updatingHealth = false; + } + } + ); + } + + showHealth(health: any) { + const modalRef = this.modalService.open(JhiHealthModalComponent); + modalRef.componentInstance.currentHealth = health; + modalRef.result.then( + result => { + // Left blank intentionally, nothing to do here + }, + reason => { + // Left blank intentionally, nothing to do here + } + ); + } + + subSystemName(name: string) { + return this.healthService.getSubSystemName(name); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.route.ts new file mode 100644 index 0000000000..0b67775651 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.route.ts @@ -0,0 +1,11 @@ +import { Route } from '@angular/router'; + +import { JhiHealthCheckComponent } from './health.component'; + +export const healthRoute: Route = { + path: 'jhi-health', + component: JhiHealthCheckComponent, + data: { + pageTitle: 'Health Checks' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.service.ts new file mode 100644 index 0000000000..4c1b0e5ec8 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/health/health.service.ts @@ -0,0 +1,133 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable({ providedIn: 'root' }) +export class JhiHealthService { + separator: string; + + constructor(private http: HttpClient) { + this.separator = '.'; + } + + checkHealth(): Observable { + return this.http.get(SERVER_API_URL + 'management/health'); + } + + transformHealthData(data): any { + const response = []; + this.flattenHealthData(response, null, data.details); + return response; + } + + getBaseName(name): string { + if (name) { + const split = name.split('.'); + return split[0]; + } + } + + getSubSystemName(name): string { + if (name) { + const split = name.split('.'); + split.splice(0, 1); + const remainder = split.join('.'); + return remainder ? ' - ' + remainder : ''; + } + } + + /* private methods */ + private addHealthObject(result, isLeaf, healthObject, name): any { + const healthData: any = { + name + }; + + const details = {}; + let hasDetails = false; + + for (const key in healthObject) { + if (healthObject.hasOwnProperty(key)) { + const value = healthObject[key]; + if (key === 'status' || key === 'error') { + healthData[key] = value; + } else { + if (!this.isHealthObject(value)) { + details[key] = value; + hasDetails = true; + } + } + } + } + + // Add the details + if (hasDetails) { + healthData.details = details; + } + + // Only add nodes if they provide additional information + if (isLeaf || hasDetails || healthData.error) { + result.push(healthData); + } + return healthData; + } + + private flattenHealthData(result, path, data): any { + for (const key in data) { + if (data.hasOwnProperty(key)) { + const value = data[key]; + if (this.isHealthObject(value)) { + if (this.hasSubSystem(value)) { + this.addHealthObject(result, false, value, this.getModuleName(path, key)); + this.flattenHealthData(result, this.getModuleName(path, key), value); + } else { + this.addHealthObject(result, true, value, this.getModuleName(path, key)); + } + } + } + } + return result; + } + + private getModuleName(path, name): string { + let result; + if (path && name) { + result = path + this.separator + name; + } else if (path) { + result = path; + } else if (name) { + result = name; + } else { + result = ''; + } + return result; + } + + private hasSubSystem(healthObject): boolean { + let result = false; + + for (const key in healthObject) { + if (healthObject.hasOwnProperty(key)) { + const value = healthObject[key]; + if (value && value.status) { + result = true; + } + } + } + return result; + } + + private isHealthObject(healthObject): boolean { + let result = false; + + for (const key in healthObject) { + if (healthObject.hasOwnProperty(key)) { + if (key === 'status') { + result = true; + } + } + } + return result; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/index.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/index.ts new file mode 100644 index 0000000000..7f631ffb9b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/index.ts @@ -0,0 +1,27 @@ +export * from './audits/audits.component'; +export * from './audits/audits.service'; +export * from './audits/audits.route'; +export * from './audits/audit.model'; +export * from './audits/audit-data.model'; +export * from './configuration/configuration.component'; +export * from './configuration/configuration.service'; +export * from './configuration/configuration.route'; +export * from './docs/docs.component'; +export * from './docs/docs.route'; +export * from './health/health.component'; +export * from './health/health-modal.component'; +export * from './health/health.service'; +export * from './health/health.route'; +export * from './logs/logs.component'; +export * from './logs/logs.service'; +export * from './logs/logs.route'; +export * from './logs/log.model'; +export * from './metrics/metrics.component'; +export * from './metrics/metrics.service'; +export * from './metrics/metrics.route'; +export * from './user-management/user-management-update.component'; +export * from './user-management/user-management-delete-dialog.component'; +export * from './user-management/user-management-detail.component'; +export * from './user-management/user-management.component'; +export * from './user-management/user-management.route'; +export * from './admin.route'; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/log.model.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/log.model.ts new file mode 100644 index 0000000000..3f27b6728c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/log.model.ts @@ -0,0 +1,3 @@ +export class Log { + constructor(public name: string, public level: string) {} +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.component.html new file mode 100644 index 0000000000..cf5d6a046f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.component.html @@ -0,0 +1,28 @@ +
+

Logs

+ +

There are {{ loggers.length }} loggers.

+ + Filter + + + + + + + + + + + + + +
NameLevel
{{logger.name | slice:0:140}} + + + + + + +
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.component.ts new file mode 100644 index 0000000000..28547f9ae6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from '@angular/core'; + +import { Log } from './log.model'; +import { LogsService } from './logs.service'; + +@Component({ + selector: 'jhi-logs', + templateUrl: './logs.component.html' +}) +export class LogsComponent implements OnInit { + loggers: Log[]; + filter: string; + orderProp: string; + reverse: boolean; + + constructor(private logsService: LogsService) { + this.filter = ''; + this.orderProp = 'name'; + this.reverse = false; + } + + ngOnInit() { + this.logsService.findAll().subscribe(response => (this.loggers = response.body)); + } + + changeLevel(name: string, level: string) { + const log = new Log(name, level); + this.logsService.changeLevel(log).subscribe(() => { + this.logsService.findAll().subscribe(response => (this.loggers = response.body)); + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.route.ts new file mode 100644 index 0000000000..cfa87715d8 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.route.ts @@ -0,0 +1,11 @@ +import { Route } from '@angular/router'; + +import { LogsComponent } from './logs.component'; + +export const logsRoute: Route = { + path: 'logs', + component: LogsComponent, + data: { + pageTitle: 'Logs' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.service.ts new file mode 100644 index 0000000000..71a596b0ab --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/logs/logs.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; +import { Log } from './log.model'; + +@Injectable({ providedIn: 'root' }) +export class LogsService { + constructor(private http: HttpClient) {} + + changeLevel(log: Log): Observable> { + return this.http.put(SERVER_API_URL + 'management/logs', log, { observe: 'response' }); + } + + findAll(): Observable> { + return this.http.get(SERVER_API_URL + 'management/logs', { observe: 'response' }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.component.html new file mode 100644 index 0000000000..75902d8fb3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.component.html @@ -0,0 +1,56 @@ +
+

+ Application Metrics + +

+ +

JVM Metrics

+
+ + + + + +
+ +
+

Garbage collector statistics

+ +
+ +
Updating...
+ + + + +
+ + + + + + + + + +
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.component.ts new file mode 100644 index 0000000000..ed508c8187 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; + +import { JhiMetricsService } from './metrics.service'; + +@Component({ + selector: 'jhi-metrics', + templateUrl: './metrics.component.html' +}) +export class JhiMetricsMonitoringComponent implements OnInit { + metrics: any = {}; + threadData: any = {}; + updatingMetrics = true; + JCACHE_KEY: string; + + constructor(private modalService: NgbModal, private metricsService: JhiMetricsService) { + this.JCACHE_KEY = 'jcache.statistics'; + } + + ngOnInit() { + this.refresh(); + } + + refresh() { + this.updatingMetrics = true; + this.metricsService.getMetrics().subscribe(metrics => { + this.metrics = metrics; + this.metricsService.threadDump().subscribe(data => { + this.threadData = data.threads; + this.updatingMetrics = false; + }); + }); + } + + isObjectExisting(metrics: any, key: string) { + return metrics && metrics[key]; + } + + isObjectExistingAndNotEmpty(metrics: any, key: string) { + return this.isObjectExisting(metrics, key) && JSON.stringify(metrics[key]) !== '{}'; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.route.ts new file mode 100644 index 0000000000..abc18b8254 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.route.ts @@ -0,0 +1,11 @@ +import { Route } from '@angular/router'; + +import { JhiMetricsMonitoringComponent } from './metrics.component'; + +export const metricsRoute: Route = { + path: 'jhi-metrics', + component: JhiMetricsMonitoringComponent, + data: { + pageTitle: 'Application Metrics' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.service.ts new file mode 100644 index 0000000000..15cfe3536c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/metrics/metrics.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable({ providedIn: 'root' }) +export class JhiMetricsService { + constructor(private http: HttpClient) {} + + getMetrics(): Observable { + return this.http.get(SERVER_API_URL + 'management/jhi-metrics'); + } + + threadDump(): Observable { + return this.http.get(SERVER_API_URL + 'management/threaddump'); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.html new file mode 100644 index 0000000000..adb1a908da --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.html @@ -0,0 +1,19 @@ +
+ + + +
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.ts new file mode 100644 index 0000000000..d7674f6cd9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.ts @@ -0,0 +1,29 @@ +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { JhiEventManager } from 'ng-jhipster'; + +import { User, UserService } from 'app/core'; + +@Component({ + selector: 'jhi-user-mgmt-delete-dialog', + templateUrl: './user-management-delete-dialog.component.html' +}) +export class UserMgmtDeleteDialogComponent { + user: User; + + constructor(private userService: UserService, public activeModal: NgbActiveModal, private eventManager: JhiEventManager) {} + + clear() { + this.activeModal.dismiss('cancel'); + } + + confirmDelete(login) { + this.userService.delete(login).subscribe(response => { + this.eventManager.broadcast({ + name: 'userListModification', + content: 'Deleted a user' + }); + this.activeModal.dismiss(true); + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-detail.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-detail.component.html new file mode 100644 index 0000000000..051f335ded --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-detail.component.html @@ -0,0 +1,47 @@ +
+
+
+

+ User [{{user.login}}] +

+
+
Login
+
+ {{user.login}} + + +
+
First Name
+
{{user.firstName}}
+
Last Name
+
{{user.lastName}}
+
Email
+
{{user.email}}
+
Created By
+
{{user.createdBy}}
+
Created Date
+
{{user.createdDate | date:'dd/MM/yy HH:mm' }}
+
Last Modified By
+
{{user.lastModifiedBy}}
+
Last Modified Date
+
{{user.lastModifiedDate | date:'dd/MM/yy HH:mm'}}
+
Profiles
+
+
    +
  • + {{authority}} +
  • +
+
+
+ +
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-detail.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-detail.component.ts new file mode 100644 index 0000000000..0b323d89a0 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-detail.component.ts @@ -0,0 +1,20 @@ +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { User } from 'app/core'; + +@Component({ + selector: 'jhi-user-mgmt-detail', + templateUrl: './user-management-detail.component.html' +}) +export class UserMgmtDetailComponent implements OnInit { + user: User; + + constructor(private route: ActivatedRoute) {} + + ngOnInit() { + this.route.data.subscribe(({ user }) => { + this.user = user.body ? user.body : user; + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-update.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-update.component.html new file mode 100644 index 0000000000..b2d04b4227 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-update.component.html @@ -0,0 +1,118 @@ +
+
+
+

+ Create or edit a User +

+
+ +
+ + +
+ +
+ + + +
+ + This field is required. + + + + This field cannot be longer than 50 characters. + + + + This field can only contain letters, digits and e-mail addresses. + +
+
+
+ + + +
+ + This field cannot be longer than 50 characters. + +
+
+
+ + + +
+ + This field cannot be longer than 50 characters. + +
+
+
+ + + +
+ + This field is required. + + + + This field cannot be longer than 100 characters. + + + + This field is required to be at least 5 characters. + + + + Your email is invalid. + +
+
+
+ +
+ +
+ + +
+
+
+ + +
+
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-update.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-update.component.ts new file mode 100644 index 0000000000..e51e4f4a33 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management-update.component.ts @@ -0,0 +1,51 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; + +import { User, UserService } from 'app/core'; + +@Component({ + selector: 'jhi-user-mgmt-update', + templateUrl: './user-management-update.component.html' +}) +export class UserMgmtUpdateComponent implements OnInit { + user: User; + languages: any[]; + authorities: any[]; + isSaving: boolean; + + constructor(private userService: UserService, private route: ActivatedRoute, private router: Router) {} + + ngOnInit() { + this.isSaving = false; + this.route.data.subscribe(({ user }) => { + this.user = user.body ? user.body : user; + }); + this.authorities = []; + this.userService.authorities().subscribe(authorities => { + this.authorities = authorities; + }); + } + + previousState() { + window.history.back(); + } + + save() { + this.isSaving = true; + if (this.user.id !== null) { + this.userService.update(this.user).subscribe(response => this.onSaveSuccess(response), () => this.onSaveError()); + } else { + this.user.langKey = 'en'; + this.userService.create(this.user).subscribe(response => this.onSaveSuccess(response), () => this.onSaveError()); + } + } + + private onSaveSuccess(result) { + this.isSaving = false; + this.previousState(); + } + + private onSaveError() { + this.isSaving = false; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.component.html new file mode 100644 index 0000000000..4592998c1f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.component.html @@ -0,0 +1,78 @@ +
+

+ Users + +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID Login Email ProfilesCreated Date Last Modified By Last Modified Date
{{user.id}}{{user.login}}{{user.email}} + + + +
+ {{ authority }} +
+
{{user.createdDate | date:'dd/MM/yy HH:mm'}}{{user.lastModifiedBy}}{{user.lastModifiedDate | date:'dd/MM/yy HH:mm'}} +
+ + + +
+
+
+
+
+ +
+
+ +
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.component.ts new file mode 100644 index 0000000000..439442e3b6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.component.ts @@ -0,0 +1,144 @@ +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { HttpResponse } from '@angular/common/http'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; + +import { ActivatedRoute, Router } from '@angular/router'; +import { JhiEventManager, JhiParseLinks, JhiAlertService } from 'ng-jhipster'; + +import { ITEMS_PER_PAGE } from 'app/shared'; +import { AccountService, UserService, User } from 'app/core'; +import { UserMgmtDeleteDialogComponent } from 'app/admin'; + +@Component({ + selector: 'jhi-user-mgmt', + templateUrl: './user-management.component.html' +}) +export class UserMgmtComponent implements OnInit, OnDestroy { + currentAccount: any; + users: User[]; + error: any; + success: any; + routeData: any; + links: any; + totalItems: any; + itemsPerPage: any; + page: any; + predicate: any; + previousPage: any; + reverse: any; + + constructor( + private userService: UserService, + private alertService: JhiAlertService, + private accountService: AccountService, + private parseLinks: JhiParseLinks, + private activatedRoute: ActivatedRoute, + private router: Router, + private eventManager: JhiEventManager, + private modalService: NgbModal + ) { + this.itemsPerPage = ITEMS_PER_PAGE; + this.routeData = this.activatedRoute.data.subscribe(data => { + this.page = data['pagingParams'].page; + this.previousPage = data['pagingParams'].page; + this.reverse = data['pagingParams'].ascending; + this.predicate = data['pagingParams'].predicate; + }); + } + + ngOnInit() { + this.accountService.identity().then(account => { + this.currentAccount = account; + this.loadAll(); + this.registerChangeInUsers(); + }); + } + + ngOnDestroy() { + this.routeData.unsubscribe(); + } + + registerChangeInUsers() { + this.eventManager.subscribe('userListModification', response => this.loadAll()); + } + + setActive(user, isActivated) { + user.activated = isActivated; + + this.userService.update(user).subscribe(response => { + if (response.status === 200) { + this.error = null; + this.success = 'OK'; + this.loadAll(); + } else { + this.success = null; + this.error = 'ERROR'; + } + }); + } + + loadAll() { + this.userService + .query({ + page: this.page - 1, + size: this.itemsPerPage, + sort: this.sort() + }) + .subscribe( + (res: HttpResponse) => this.onSuccess(res.body, res.headers), + (res: HttpResponse) => this.onError(res.body) + ); + } + + trackIdentity(index, item: User) { + return item.id; + } + + sort() { + const result = [this.predicate + ',' + (this.reverse ? 'asc' : 'desc')]; + if (this.predicate !== 'id') { + result.push('id'); + } + return result; + } + + loadPage(page: number) { + if (page !== this.previousPage) { + this.previousPage = page; + this.transition(); + } + } + + transition() { + this.router.navigate(['/admin/user-management'], { + queryParams: { + page: this.page, + sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc') + } + }); + this.loadAll(); + } + + deleteUser(user: User) { + const modalRef = this.modalService.open(UserMgmtDeleteDialogComponent, { size: 'lg', backdrop: 'static' }); + modalRef.componentInstance.user = user; + modalRef.result.then( + result => { + // Left blank intentionally, nothing to do here + }, + reason => { + // Left blank intentionally, nothing to do here + } + ); + } + + private onSuccess(data, headers) { + this.links = this.parseLinks.parse(headers.get('link')); + this.totalItems = headers.get('X-Total-Count'); + this.users = data; + } + + private onError(error) { + this.alertService.error(error.error, error.message, null); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.route.ts new file mode 100644 index 0000000000..bf1115516f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/admin/user-management/user-management.route.ts @@ -0,0 +1,68 @@ +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Routes, CanActivate } from '@angular/router'; +import { JhiPaginationUtil, JhiResolvePagingParams } from 'ng-jhipster'; + +import { AccountService, User, UserService } from 'app/core'; +import { UserMgmtComponent } from './user-management.component'; +import { UserMgmtDetailComponent } from './user-management-detail.component'; +import { UserMgmtUpdateComponent } from './user-management-update.component'; + +@Injectable({ providedIn: 'root' }) +export class UserResolve implements CanActivate { + constructor(private accountService: AccountService) {} + + canActivate() { + return this.accountService.identity().then(account => this.accountService.hasAnyAuthority(['ROLE_ADMIN'])); + } +} + +@Injectable({ providedIn: 'root' }) +export class UserMgmtResolve implements Resolve { + constructor(private service: UserService) {} + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + const id = route.params['login'] ? route.params['login'] : null; + if (id) { + return this.service.find(id); + } + return new User(); + } +} + +export const userMgmtRoute: Routes = [ + { + path: 'user-management', + component: UserMgmtComponent, + resolve: { + pagingParams: JhiResolvePagingParams + }, + data: { + pageTitle: 'Users', + defaultSort: 'id,asc' + } + }, + { + path: 'user-management/:login/view', + component: UserMgmtDetailComponent, + resolve: { + user: UserMgmtResolve + }, + data: { + pageTitle: 'Users' + } + }, + { + path: 'user-management/new', + component: UserMgmtUpdateComponent, + resolve: { + user: UserMgmtResolve + } + }, + { + path: 'user-management/:login/edit', + component: UserMgmtUpdateComponent, + resolve: { + user: UserMgmtResolve + } + } +]; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/app-routing.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/app-routing.module.ts new file mode 100644 index 0000000000..c40d4df774 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/app-routing.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { errorRoute, navbarRoute } from './layouts'; +import { DEBUG_INFO_ENABLED } from 'app/app.constants'; + +const LAYOUT_ROUTES = [navbarRoute, ...errorRoute]; + +@NgModule({ + imports: [ + RouterModule.forRoot( + [ + { + path: 'admin', + loadChildren: './admin/admin.module#BookstoreAdminModule' + }, + ...LAYOUT_ROUTES + ], + { useHash: true, enableTracing: DEBUG_INFO_ENABLED } + ) + ], + exports: [RouterModule] +}) +export class BookstoreAppRoutingModule {} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/app.constants.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/app.constants.ts new file mode 100644 index 0000000000..9760a49a91 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/app.constants.ts @@ -0,0 +1,8 @@ +// These constants are injected via webpack environment variables. +// You can add more variables in webpack.common.js or in profile specific webpack..js files. +// If you change the values in the webpack config files, you need to re run webpack to update the application + +export const VERSION = process.env.VERSION; +export const DEBUG_INFO_ENABLED: boolean = !!process.env.DEBUG_INFO_ENABLED; +export const SERVER_API_URL = process.env.SERVER_API_URL; +export const BUILD_TIMESTAMP = process.env.BUILD_TIMESTAMP; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/app.main.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/app.main.ts new file mode 100644 index 0000000000..7695bb8571 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/app.main.ts @@ -0,0 +1,14 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { ProdConfig } from './blocks/config/prod.config'; +import { BookstoreAppModule } from './app.module'; + +ProdConfig(); + +if (module['hot']) { + module['hot'].accept(); +} + +platformBrowserDynamic() + .bootstrapModule(BookstoreAppModule, { preserveWhitespaces: true }) + .then(success => console.log(`Application started`)) + .catch(err => console.error(err)); diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/app.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/app.module.ts new file mode 100644 index 0000000000..5fb96ed8c5 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/app.module.ts @@ -0,0 +1,70 @@ +import './vendor.ts'; + +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { HTTP_INTERCEPTORS } from '@angular/common/http'; +import { NgbDatepickerConfig } from '@ng-bootstrap/ng-bootstrap'; +import { Ng2Webstorage } from 'ngx-webstorage'; +import { NgJhipsterModule } from 'ng-jhipster'; + +import { AuthInterceptor } from './blocks/interceptor/auth.interceptor'; +import { AuthExpiredInterceptor } from './blocks/interceptor/auth-expired.interceptor'; +import { ErrorHandlerInterceptor } from './blocks/interceptor/errorhandler.interceptor'; +import { NotificationInterceptor } from './blocks/interceptor/notification.interceptor'; +import { BookstoreSharedModule } from 'app/shared'; +import { BookstoreCoreModule } from 'app/core'; +import { BookstoreAppRoutingModule } from './app-routing.module'; +import { BookstoreHomeModule } from './home/home.module'; +import { BookstoreAccountModule } from './account/account.module'; +import { BookstoreEntityModule } from './entities/entity.module'; +import * as moment from 'moment'; +// jhipster-needle-angular-add-module-import JHipster will add new module here +import { JhiMainComponent, NavbarComponent, FooterComponent, PageRibbonComponent, ErrorComponent } from './layouts'; + +@NgModule({ + imports: [ + BrowserModule, + Ng2Webstorage.forRoot({ prefix: 'jhi', separator: '-' }), + NgJhipsterModule.forRoot({ + // set below to true to make alerts look like toast + alertAsToast: false, + alertTimeout: 5000 + }), + BookstoreSharedModule.forRoot(), + BookstoreCoreModule, + BookstoreHomeModule, + BookstoreAccountModule, + // jhipster-needle-angular-add-module JHipster will add new module here + BookstoreEntityModule, + BookstoreAppRoutingModule + ], + declarations: [JhiMainComponent, NavbarComponent, ErrorComponent, PageRibbonComponent, FooterComponent], + providers: [ + { + provide: HTTP_INTERCEPTORS, + useClass: AuthInterceptor, + multi: true + }, + { + provide: HTTP_INTERCEPTORS, + useClass: AuthExpiredInterceptor, + multi: true + }, + { + provide: HTTP_INTERCEPTORS, + useClass: ErrorHandlerInterceptor, + multi: true + }, + { + provide: HTTP_INTERCEPTORS, + useClass: NotificationInterceptor, + multi: true + } + ], + bootstrap: [JhiMainComponent] +}) +export class BookstoreAppModule { + constructor(private dpConfig: NgbDatepickerConfig) { + this.dpConfig.minDate = { year: moment().year() - 100, month: 1, day: 1 }; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/config/prod.config.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/config/prod.config.ts new file mode 100644 index 0000000000..c6221c1eaf --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/config/prod.config.ts @@ -0,0 +1,9 @@ +import { enableProdMode } from '@angular/core'; +import { DEBUG_INFO_ENABLED } from 'app/app.constants'; + +export function ProdConfig() { + // disable debug data on prod profile to improve performance + if (!DEBUG_INFO_ENABLED) { + enableProdMode(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/config/uib-pagination.config.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/config/uib-pagination.config.ts new file mode 100644 index 0000000000..0c2ea94808 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/config/uib-pagination.config.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@angular/core'; +import { NgbPaginationConfig } from '@ng-bootstrap/ng-bootstrap'; +import { ITEMS_PER_PAGE } from 'app/shared'; + +@Injectable({ providedIn: 'root' }) +export class PaginationConfig { + // tslint:disable-next-line: no-unused-variable + constructor(private config: NgbPaginationConfig) { + config.boundaryLinks = true; + config.maxSize = 5; + config.pageSize = ITEMS_PER_PAGE; + config.size = 'sm'; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/auth-expired.interceptor.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/auth-expired.interceptor.ts new file mode 100644 index 0000000000..bc1b70cfef --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/auth-expired.interceptor.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@angular/core'; +import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; +import { LoginService } from 'app/core/login/login.service'; + +@Injectable() +export class AuthExpiredInterceptor implements HttpInterceptor { + constructor(private loginService: LoginService) {} + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + return next.handle(request).pipe( + tap( + (event: HttpEvent) => {}, + (err: any) => { + if (err instanceof HttpErrorResponse) { + if (err.status === 401) { + this.loginService.logout(); + } + } + } + ) + ); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/auth.interceptor.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/auth.interceptor.ts new file mode 100644 index 0000000000..23cdeaf66b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/auth.interceptor.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { LocalStorageService, SessionStorageService } from 'ngx-webstorage'; +import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable() +export class AuthInterceptor implements HttpInterceptor { + constructor(private localStorage: LocalStorageService, private sessionStorage: SessionStorageService) {} + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + if (!request || !request.url || (/^http/.test(request.url) && !(SERVER_API_URL && request.url.startsWith(SERVER_API_URL)))) { + return next.handle(request); + } + + const token = this.localStorage.retrieve('authenticationToken') || this.sessionStorage.retrieve('authenticationToken'); + if (!!token) { + request = request.clone({ + setHeaders: { + Authorization: 'Bearer ' + token + } + }); + } + return next.handle(request); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/errorhandler.interceptor.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/errorhandler.interceptor.ts new file mode 100644 index 0000000000..e464f66cd3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/errorhandler.interceptor.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@angular/core'; +import { JhiEventManager } from 'ng-jhipster'; +import { HttpInterceptor, HttpRequest, HttpErrorResponse, HttpHandler, HttpEvent } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; + +@Injectable() +export class ErrorHandlerInterceptor implements HttpInterceptor { + constructor(private eventManager: JhiEventManager) {} + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + return next.handle(request).pipe( + tap( + (event: HttpEvent) => {}, + (err: any) => { + if (err instanceof HttpErrorResponse) { + if (!(err.status === 401 && (err.message === '' || (err.url && err.url.includes('/api/account'))))) { + this.eventManager.broadcast({ name: 'bookstoreApp.httpError', content: err }); + } + } + } + ) + ); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/notification.interceptor.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/notification.interceptor.ts new file mode 100644 index 0000000000..34af81d482 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/blocks/interceptor/notification.interceptor.ts @@ -0,0 +1,34 @@ +import { JhiAlertService } from 'ng-jhipster'; +import { HttpInterceptor, HttpRequest, HttpResponse, HttpHandler, HttpEvent } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { tap } from 'rxjs/operators'; + +@Injectable() +export class NotificationInterceptor implements HttpInterceptor { + constructor(private alertService: JhiAlertService) {} + + intercept(request: HttpRequest, next: HttpHandler): Observable> { + return next.handle(request).pipe( + tap( + (event: HttpEvent) => { + if (event instanceof HttpResponse) { + const arr = event.headers.keys(); + let alert = null; + arr.forEach(entry => { + if (entry.toLowerCase().endsWith('app-alert')) { + alert = event.headers.get(entry); + } + }); + if (alert) { + if (typeof alert === 'string') { + this.alertService.success(alert, null, null); + } + } + } + }, + (err: any) => {} + ) + ); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/account.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/account.service.ts new file mode 100644 index 0000000000..a6548f6dd9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/account.service.ts @@ -0,0 +1,108 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpResponse } from '@angular/common/http'; +import { Observable, Subject } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; +import { Account } from 'app/core/user/account.model'; + +@Injectable({ providedIn: 'root' }) +export class AccountService { + private userIdentity: any; + private authenticated = false; + private authenticationState = new Subject(); + + constructor(private http: HttpClient) {} + + fetch(): Observable> { + return this.http.get(SERVER_API_URL + 'api/account', { observe: 'response' }); + } + + save(account: any): Observable> { + return this.http.post(SERVER_API_URL + 'api/account', account, { observe: 'response' }); + } + + authenticate(identity) { + this.userIdentity = identity; + this.authenticated = identity !== null; + this.authenticationState.next(this.userIdentity); + } + + hasAnyAuthority(authorities: string[]): boolean { + if (!this.authenticated || !this.userIdentity || !this.userIdentity.authorities) { + return false; + } + + for (let i = 0; i < authorities.length; i++) { + if (this.userIdentity.authorities.includes(authorities[i])) { + return true; + } + } + + return false; + } + + hasAuthority(authority: string): Promise { + if (!this.authenticated) { + return Promise.resolve(false); + } + + return this.identity().then( + id => { + return Promise.resolve(id.authorities && id.authorities.includes(authority)); + }, + () => { + return Promise.resolve(false); + } + ); + } + + identity(force?: boolean): Promise { + if (force) { + this.userIdentity = undefined; + } + + // check and see if we have retrieved the userIdentity data from the server. + // if we have, reuse it by immediately resolving + if (this.userIdentity) { + return Promise.resolve(this.userIdentity); + } + + // retrieve the userIdentity data from the server, update the identity object, and then resolve. + return this.fetch() + .toPromise() + .then(response => { + const account = response.body; + if (account) { + this.userIdentity = account; + this.authenticated = true; + } else { + this.userIdentity = null; + this.authenticated = false; + } + this.authenticationState.next(this.userIdentity); + return this.userIdentity; + }) + .catch(err => { + this.userIdentity = null; + this.authenticated = false; + this.authenticationState.next(this.userIdentity); + return null; + }); + } + + isAuthenticated(): boolean { + return this.authenticated; + } + + isIdentityResolved(): boolean { + return this.userIdentity !== undefined; + } + + getAuthenticationState(): Observable { + return this.authenticationState.asObservable(); + } + + getImageUrl(): string { + return this.isIdentityResolved() ? this.userIdentity.imageUrl : null; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/auth-jwt.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/auth-jwt.service.ts new file mode 100644 index 0000000000..5ad53e3dfe --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/auth-jwt.service.ts @@ -0,0 +1,59 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { LocalStorageService, SessionStorageService } from 'ngx-webstorage'; + +import { SERVER_API_URL } from 'app/app.constants'; + +@Injectable({ providedIn: 'root' }) +export class AuthServerProvider { + constructor(private http: HttpClient, private $localStorage: LocalStorageService, private $sessionStorage: SessionStorageService) {} + + getToken() { + return this.$localStorage.retrieve('authenticationToken') || this.$sessionStorage.retrieve('authenticationToken'); + } + + login(credentials): Observable { + const data = { + username: credentials.username, + password: credentials.password, + rememberMe: credentials.rememberMe + }; + return this.http.post(SERVER_API_URL + 'api/authenticate', data, { observe: 'response' }).pipe(map(authenticateSuccess.bind(this))); + + function authenticateSuccess(resp) { + const bearerToken = resp.headers.get('Authorization'); + if (bearerToken && bearerToken.slice(0, 7) === 'Bearer ') { + const jwt = bearerToken.slice(7, bearerToken.length); + this.storeAuthenticationToken(jwt, credentials.rememberMe); + return jwt; + } + } + } + + loginWithToken(jwt, rememberMe) { + if (jwt) { + this.storeAuthenticationToken(jwt, rememberMe); + return Promise.resolve(jwt); + } else { + return Promise.reject('auth-jwt-service Promise reject'); // Put appropriate error message here + } + } + + storeAuthenticationToken(jwt, rememberMe) { + if (rememberMe) { + this.$localStorage.store('authenticationToken', jwt); + } else { + this.$sessionStorage.store('authenticationToken', jwt); + } + } + + logout(): Observable { + return new Observable(observer => { + this.$localStorage.clear('authenticationToken'); + this.$sessionStorage.clear('authenticationToken'); + observer.complete(); + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/csrf.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/csrf.service.ts new file mode 100644 index 0000000000..01fdccb02a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/csrf.service.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@angular/core'; +import { CookieService } from 'ngx-cookie'; + +@Injectable({ providedIn: 'root' }) +export class CSRFService { + constructor(private cookieService: CookieService) {} + + getCSRF(name = 'XSRF-TOKEN') { + return this.cookieService.get(name); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/state-storage.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/state-storage.service.ts new file mode 100644 index 0000000000..0e5befbfc3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/state-storage.service.ts @@ -0,0 +1,46 @@ +import { Injectable } from '@angular/core'; +import { SessionStorageService } from 'ngx-webstorage'; + +@Injectable({ providedIn: 'root' }) +export class StateStorageService { + constructor(private $sessionStorage: SessionStorageService) {} + + getPreviousState() { + return this.$sessionStorage.retrieve('previousState'); + } + + resetPreviousState() { + this.$sessionStorage.clear('previousState'); + } + + storePreviousState(previousStateName, previousStateParams) { + const previousState = { name: previousStateName, params: previousStateParams }; + this.$sessionStorage.store('previousState', previousState); + } + + getDestinationState() { + return this.$sessionStorage.retrieve('destinationState'); + } + + storeUrl(url: string) { + this.$sessionStorage.store('previousUrl', url); + } + + getUrl() { + return this.$sessionStorage.retrieve('previousUrl'); + } + + storeDestinationState(destinationState, destinationStateParams, fromState) { + const destinationInfo = { + destination: { + name: destinationState.name, + data: destinationState.data + }, + params: destinationStateParams, + from: { + name: fromState.name + } + }; + this.$sessionStorage.store('destinationState', destinationInfo); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/user-route-access-service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/user-route-access-service.ts new file mode 100644 index 0000000000..a55b0bc035 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/auth/user-route-access-service.ts @@ -0,0 +1,52 @@ +import { Injectable, isDevMode } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; + +import { AccountService } from '../'; +import { LoginModalService } from '../login/login-modal.service'; +import { StateStorageService } from './state-storage.service'; + +@Injectable({ providedIn: 'root' }) +export class UserRouteAccessService implements CanActivate { + constructor( + private router: Router, + private loginModalService: LoginModalService, + private accountService: AccountService, + private stateStorageService: StateStorageService + ) {} + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Promise { + const authorities = route.data['authorities']; + // We need to call the checkLogin / and so the accountService.identity() function, to ensure, + // that the client has a principal too, if they already logged in by the server. + // This could happen on a page refresh. + return this.checkLogin(authorities, state.url); + } + + checkLogin(authorities: string[], url: string): Promise { + return this.accountService.identity().then(account => { + if (!authorities || authorities.length === 0) { + return true; + } + + if (account) { + const hasAnyAuthority = this.accountService.hasAnyAuthority(authorities); + if (hasAnyAuthority) { + return true; + } + if (isDevMode()) { + console.error('User has not any of required authorities: ', authorities); + } + return false; + } + + this.stateStorageService.storeUrl(url); + this.router.navigate(['accessdenied']).then(() => { + // only show the login dialog, if the user hasn't logged in yet + if (!account) { + this.loginModalService.open(); + } + }); + return false; + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/core.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/core.module.ts new file mode 100644 index 0000000000..7569b8f59e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/core.module.ts @@ -0,0 +1,24 @@ +import { NgModule, LOCALE_ID } from '@angular/core'; +import { DatePipe, registerLocaleData } from '@angular/common'; +import { HttpClientModule } from '@angular/common/http'; +import { Title } from '@angular/platform-browser'; +import locale from '@angular/common/locales/en'; + +@NgModule({ + imports: [HttpClientModule], + exports: [], + declarations: [], + providers: [ + Title, + { + provide: LOCALE_ID, + useValue: 'en' + }, + DatePipe + ] +}) +export class BookstoreCoreModule { + constructor() { + registerLocaleData(locale); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/index.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/index.ts new file mode 100644 index 0000000000..38827443a5 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/index.ts @@ -0,0 +1,11 @@ +export * from './auth/csrf.service'; +export * from './auth/state-storage.service'; +export * from './auth/account.service'; +export * from './auth/auth-jwt.service'; +export * from './user/account.model'; +export * from './user/user.model'; +export * from './auth/user-route-access-service'; +export * from './login/login-modal.service'; +export * from './login/login.service'; +export * from './user/user.service'; +export * from './core.module'; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/login/login-modal.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/login/login-modal.service.ts new file mode 100644 index 0000000000..a0002aa56b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/login/login-modal.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from '@angular/core'; +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; + +import { JhiLoginModalComponent } from 'app/shared/login/login.component'; + +@Injectable({ providedIn: 'root' }) +export class LoginModalService { + private isOpen = false; + constructor(private modalService: NgbModal) {} + + open(): NgbModalRef { + if (this.isOpen) { + return; + } + this.isOpen = true; + const modalRef = this.modalService.open(JhiLoginModalComponent); + modalRef.result.then( + result => { + this.isOpen = false; + }, + reason => { + this.isOpen = false; + } + ); + return modalRef; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/login/login.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/login/login.service.ts new file mode 100644 index 0000000000..e91508ff44 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/login/login.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from '@angular/core'; + +import { AccountService } from 'app/core/auth/account.service'; +import { AuthServerProvider } from 'app/core/auth/auth-jwt.service'; + +@Injectable({ providedIn: 'root' }) +export class LoginService { + constructor(private accountService: AccountService, private authServerProvider: AuthServerProvider) {} + + login(credentials, callback?) { + const cb = callback || function() {}; + + return new Promise((resolve, reject) => { + this.authServerProvider.login(credentials).subscribe( + data => { + this.accountService.identity(true).then(account => { + resolve(data); + }); + return cb(); + }, + err => { + this.logout(); + reject(err); + return cb(err); + } + ); + }); + } + + loginWithToken(jwt, rememberMe) { + return this.authServerProvider.loginWithToken(jwt, rememberMe); + } + + logout() { + this.authServerProvider.logout().subscribe(); + this.accountService.authenticate(null); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/account.model.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/account.model.ts new file mode 100644 index 0000000000..35679657e3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/account.model.ts @@ -0,0 +1,12 @@ +export class Account { + constructor( + public activated: boolean, + public authorities: string[], + public email: string, + public firstName: string, + public langKey: string, + public lastName: string, + public login: string, + public imageUrl: string + ) {} +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/user.model.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/user.model.ts new file mode 100644 index 0000000000..e82da11ac5 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/user.model.ts @@ -0,0 +1,47 @@ +export interface IUser { + id?: any; + login?: string; + firstName?: string; + lastName?: string; + email?: string; + activated?: boolean; + langKey?: string; + authorities?: any[]; + createdBy?: string; + createdDate?: Date; + lastModifiedBy?: string; + lastModifiedDate?: Date; + password?: string; +} + +export class User implements IUser { + constructor( + public id?: any, + public login?: string, + public firstName?: string, + public lastName?: string, + public email?: string, + public activated?: boolean, + public langKey?: string, + public authorities?: any[], + public createdBy?: string, + public createdDate?: Date, + public lastModifiedBy?: string, + public lastModifiedDate?: Date, + public password?: string + ) { + this.id = id ? id : null; + this.login = login ? login : null; + this.firstName = firstName ? firstName : null; + this.lastName = lastName ? lastName : null; + this.email = email ? email : null; + this.activated = activated ? activated : false; + this.langKey = langKey ? langKey : null; + this.authorities = authorities ? authorities : null; + this.createdBy = createdBy ? createdBy : null; + this.createdDate = createdDate ? createdDate : null; + this.lastModifiedBy = lastModifiedBy ? lastModifiedBy : null; + this.lastModifiedDate = lastModifiedDate ? lastModifiedDate : null; + this.password = password ? password : null; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/user.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/user.service.ts new file mode 100644 index 0000000000..5c8065bedd --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/core/user/user.service.ts @@ -0,0 +1,39 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +import { SERVER_API_URL } from 'app/app.constants'; +import { createRequestOption } from 'app/shared/util/request-util'; +import { IUser } from './user.model'; + +@Injectable({ providedIn: 'root' }) +export class UserService { + public resourceUrl = SERVER_API_URL + 'api/users'; + + constructor(private http: HttpClient) {} + + create(user: IUser): Observable> { + return this.http.post(this.resourceUrl, user, { observe: 'response' }); + } + + update(user: IUser): Observable> { + return this.http.put(this.resourceUrl, user, { observe: 'response' }); + } + + find(login: string): Observable> { + return this.http.get(`${this.resourceUrl}/${login}`, { observe: 'response' }); + } + + query(req?: any): Observable> { + const options = createRequestOption(req); + return this.http.get(this.resourceUrl, { params: options, observe: 'response' }); + } + + delete(login: string): Observable> { + return this.http.delete(`${this.resourceUrl}/${login}`, { observe: 'response' }); + } + + authorities(): Observable { + return this.http.get(SERVER_API_URL + 'api/users/authorities'); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/entity.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/entity.module.ts new file mode 100644 index 0000000000..b0f67260c7 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/entity.module.ts @@ -0,0 +1,15 @@ +import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +@NgModule({ + imports: [ + RouterModule.forChild([ + /* jhipster-needle-add-entity-route - JHipster will add entity modules routes here */ + ]) + ], + declarations: [], + entryComponents: [], + providers: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BookstoreEntityModule {} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.component.html new file mode 100644 index 0000000000..0c595b9d74 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.component.html @@ -0,0 +1,41 @@ +
+
+ +
+
+

Welcome, Java Hipster!

+

This is your homepage

+ +
+
+ You are logged in as user "{{account.login}}". +
+ +
+ If you want to + sign in, you can try the default accounts:
- Administrator (login="admin" and password="admin")
- User (login="user" and password="user").
+
+
+ You don't have an account yet?  + Register a new account +
+
+ +

+ If you have any question on JHipster: +

+ + + +

+ If you like JHipster, don't forget to give us a star on GitHub! +

+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.component.ts new file mode 100644 index 0000000000..f1410c2cf5 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.component.ts @@ -0,0 +1,44 @@ +import { Component, OnInit } from '@angular/core'; +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { JhiEventManager } from 'ng-jhipster'; + +import { LoginModalService, AccountService, Account } from 'app/core'; + +@Component({ + selector: 'jhi-home', + templateUrl: './home.component.html', + styleUrls: ['home.scss'] +}) +export class HomeComponent implements OnInit { + account: Account; + modalRef: NgbModalRef; + + constructor( + private accountService: AccountService, + private loginModalService: LoginModalService, + private eventManager: JhiEventManager + ) {} + + ngOnInit() { + this.accountService.identity().then((account: Account) => { + this.account = account; + }); + this.registerAuthenticationSuccess(); + } + + registerAuthenticationSuccess() { + this.eventManager.subscribe('authenticationSuccess', message => { + this.accountService.identity().then(account => { + this.account = account; + }); + }); + } + + isAuthenticated() { + return this.accountService.isAuthenticated(); + } + + login() { + this.modalRef = this.loginModalService.open(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.module.ts new file mode 100644 index 0000000000..c1004a6dd9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.module.ts @@ -0,0 +1,12 @@ +import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { BookstoreSharedModule } from 'app/shared'; +import { HOME_ROUTE, HomeComponent } from './'; + +@NgModule({ + imports: [BookstoreSharedModule, RouterModule.forChild([HOME_ROUTE])], + declarations: [HomeComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BookstoreHomeModule {} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.route.ts new file mode 100644 index 0000000000..a59993f8f0 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.route.ts @@ -0,0 +1,12 @@ +import { Route } from '@angular/router'; + +import { HomeComponent } from './'; + +export const HOME_ROUTE: Route = { + path: '', + component: HomeComponent, + data: { + authorities: [], + pageTitle: 'Welcome, Java Hipster!' + } +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.scss b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.scss new file mode 100644 index 0000000000..7fe48ff5fa --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/home.scss @@ -0,0 +1,23 @@ +/* ========================================================================== +Main page styles +========================================================================== */ + +.hipster { + display: inline-block; + width: 347px; + height: 497px; + background: url('../../content/images/jhipster_family_member_0.svg') no-repeat center top; + background-size: contain; +} + +/* wait autoprefixer update to allow simple generation of high pixel density media query */ +@media only screen and (-webkit-min-device-pixel-ratio: 2), + only screen and (-moz-min-device-pixel-ratio: 2), + only screen and (-o-min-device-pixel-ratio: 2/1), + only screen and (min-resolution: 192dpi), + only screen and (min-resolution: 2dppx) { + .hipster { + background: url('../../content/images/jhipster_family_member_0.svg') no-repeat center top; + background-size: contain; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/home/index.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/index.ts new file mode 100644 index 0000000000..d76285b277 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/home/index.ts @@ -0,0 +1,3 @@ +export * from './home.component'; +export * from './home.route'; +export * from './home.module'; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.component.html new file mode 100644 index 0000000000..b79392173e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.component.html @@ -0,0 +1,19 @@ +
+
+
+ +
+
+

Error Page!

+ +
+
{{errorMessage}} +
+
+
You are not authorized to access this page. +
+
The page asked was not found. +
+
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.component.ts new file mode 100644 index 0000000000..faa9658161 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +@Component({ + selector: 'jhi-error', + templateUrl: './error.component.html' +}) +export class ErrorComponent implements OnInit { + errorMessage: string; + error403: boolean; + error404: boolean; + + constructor(private route: ActivatedRoute) {} + + ngOnInit() { + this.route.data.subscribe(routeData => { + if (routeData.error403) { + this.error403 = routeData.error403; + } + if (routeData.error404) { + this.error404 = routeData.error404; + } + if (routeData.errorMessage) { + this.errorMessage = routeData.errorMessage; + } + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.route.ts new file mode 100644 index 0000000000..85ab257ca9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/error/error.route.ts @@ -0,0 +1,36 @@ +import { Routes } from '@angular/router'; + +import { ErrorComponent } from './error.component'; + +export const errorRoute: Routes = [ + { + path: 'error', + component: ErrorComponent, + data: { + authorities: [], + pageTitle: 'Bookstore' + } + }, + { + path: 'accessdenied', + component: ErrorComponent, + data: { + authorities: [], + pageTitle: 'Bookstore', + error403: true + } + }, + { + path: '404', + component: ErrorComponent, + data: { + authorities: [], + pageTitle: 'Bookstore', + error404: true + } + }, + { + path: '**', + redirectTo: '/404' + } +]; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/footer/footer.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/footer/footer.component.html new file mode 100644 index 0000000000..b3ba632e02 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/footer/footer.component.html @@ -0,0 +1,3 @@ + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/footer/footer.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/footer/footer.component.ts new file mode 100644 index 0000000000..37da8bca75 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/footer/footer.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'jhi-footer', + templateUrl: './footer.component.html' +}) +export class FooterComponent {} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/index.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/index.ts new file mode 100644 index 0000000000..8cbf6368d7 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/index.ts @@ -0,0 +1,9 @@ +export * from './error/error.component'; +export * from './error/error.route'; +export * from './main/main.component'; +export * from './footer/footer.component'; +export * from './navbar/navbar.component'; +export * from './navbar/navbar.route'; +export * from './profiles/page-ribbon.component'; +export * from './profiles/profile.service'; +export * from './profiles/profile-info.model'; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/main/main.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/main/main.component.html new file mode 100644 index 0000000000..5bcd12ab0b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/main/main.component.html @@ -0,0 +1,11 @@ + +
+ +
+
+
+ + +
+ +
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/main/main.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/main/main.component.ts new file mode 100644 index 0000000000..e1f2c8134e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/main/main.component.ts @@ -0,0 +1,31 @@ +import { Component, OnInit } from '@angular/core'; +import { Router, ActivatedRouteSnapshot, NavigationEnd, NavigationError } from '@angular/router'; + +import { Title } from '@angular/platform-browser'; + +@Component({ + selector: 'jhi-main', + templateUrl: './main.component.html' +}) +export class JhiMainComponent implements OnInit { + constructor(private titleService: Title, private router: Router) {} + + private getPageTitle(routeSnapshot: ActivatedRouteSnapshot) { + let title: string = routeSnapshot.data && routeSnapshot.data['pageTitle'] ? routeSnapshot.data['pageTitle'] : 'bookstoreApp'; + if (routeSnapshot.firstChild) { + title = this.getPageTitle(routeSnapshot.firstChild) || title; + } + return title; + } + + ngOnInit() { + this.router.events.subscribe(event => { + if (event instanceof NavigationEnd) { + this.titleService.setTitle(this.getPageTitle(this.router.routerState.snapshot.root)); + } + if (event instanceof NavigationError && event.error.status === 404) { + this.router.navigate(['/404']); + } + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.html new file mode 100644 index 0000000000..bd3e80b3cb --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.html @@ -0,0 +1,139 @@ + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.ts new file mode 100644 index 0000000000..6e00d7a1cb --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.ts @@ -0,0 +1,65 @@ +import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; + +import { VERSION } from 'app/app.constants'; +import { AccountService, LoginModalService, LoginService } from 'app/core'; +import { ProfileService } from 'app/layouts/profiles/profile.service'; + +@Component({ + selector: 'jhi-navbar', + templateUrl: './navbar.component.html', + styleUrls: ['navbar.scss'] +}) +export class NavbarComponent implements OnInit { + inProduction: boolean; + isNavbarCollapsed: boolean; + languages: any[]; + swaggerEnabled: boolean; + modalRef: NgbModalRef; + version: string; + + constructor( + private loginService: LoginService, + private accountService: AccountService, + private loginModalService: LoginModalService, + private profileService: ProfileService, + private router: Router + ) { + this.version = VERSION ? 'v' + VERSION : ''; + this.isNavbarCollapsed = true; + } + + ngOnInit() { + this.profileService.getProfileInfo().then(profileInfo => { + this.inProduction = profileInfo.inProduction; + this.swaggerEnabled = profileInfo.swaggerEnabled; + }); + } + + collapseNavbar() { + this.isNavbarCollapsed = true; + } + + isAuthenticated() { + return this.accountService.isAuthenticated(); + } + + login() { + this.modalRef = this.loginModalService.open(); + } + + logout() { + this.collapseNavbar(); + this.loginService.logout(); + this.router.navigate(['']); + } + + toggleNavbar() { + this.isNavbarCollapsed = !this.isNavbarCollapsed; + } + + getImageUrl() { + return this.isAuthenticated() ? this.accountService.getImageUrl() : null; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.route.ts new file mode 100644 index 0000000000..317d99604b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.route.ts @@ -0,0 +1,9 @@ +import { Route } from '@angular/router'; + +import { NavbarComponent } from './navbar.component'; + +export const navbarRoute: Route = { + path: '', + component: NavbarComponent, + outlet: 'navbar' +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.scss b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.scss new file mode 100644 index 0000000000..9a5f929293 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.scss @@ -0,0 +1,53 @@ +@import '~bootstrap/scss/functions'; +@import '~bootstrap/scss/variables'; + +/* ========================================================================== +Navbar +========================================================================== */ + +.navbar-version { + font-size: 0.65em; + color: $navbar-dark-color; +} + +.profile-image { + height: 1.75em; + width: 1.75em; +} + +.navbar { + padding: 0.2rem 1rem; + .dropdown-item.active, + .dropdown-item.active:focus, + .dropdown-item.active:hover { + background-color: $dark; + } + + ul.navbar-nav { + .nav-item { + margin-left: 0.5em; + } + } + + a.nav-link { + font-weight: 400; + } + + .navbar-toggler { + &:hover { + color: $navbar-dark-hover-color; + } + } +} + +/* ========================================================================== +Logo styles +========================================================================== */ +.logo-img { + height: 45px; + width: 45px; + display: inline-block; + vertical-align: middle; + background: url('../../../content/images/logo-jhipster.png') no-repeat center center; + background-size: contain; +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/page-ribbon.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/page-ribbon.component.ts new file mode 100644 index 0000000000..00fe76075d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/page-ribbon.component.ts @@ -0,0 +1,26 @@ +import { Component, OnInit } from '@angular/core'; +import { ProfileService } from './profile.service'; +import { ProfileInfo } from './profile-info.model'; + +@Component({ + selector: 'jhi-page-ribbon', + template: ` + + `, + styleUrls: ['page-ribbon.scss'] +}) +export class PageRibbonComponent implements OnInit { + profileInfo: ProfileInfo; + ribbonEnv: string; + + constructor(private profileService: ProfileService) {} + + ngOnInit() { + this.profileService.getProfileInfo().then(profileInfo => { + this.profileInfo = profileInfo; + this.ribbonEnv = profileInfo.ribbonEnv; + }); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/page-ribbon.scss b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/page-ribbon.scss new file mode 100644 index 0000000000..90125b70cb --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/page-ribbon.scss @@ -0,0 +1,31 @@ +/* ========================================================================== +Developement Ribbon +========================================================================== */ +.ribbon { + background-color: rgba(170, 0, 0, 0.5); + left: -3.5em; + -moz-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + -o-transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + overflow: hidden; + position: absolute; + top: 40px; + white-space: nowrap; + width: 15em; + z-index: 9999; + pointer-events: none; + opacity: 0.75; + a { + color: #fff; + display: block; + font-weight: 400; + margin: 1px 0; + padding: 10px 50px; + text-align: center; + text-decoration: none; + text-shadow: 0 0 5px #444; + pointer-events: none; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/profile-info.model.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/profile-info.model.ts new file mode 100644 index 0000000000..f1adc52c7b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/profile-info.model.ts @@ -0,0 +1,6 @@ +export class ProfileInfo { + activeProfiles: string[]; + ribbonEnv: string; + inProduction: boolean; + swaggerEnabled: boolean; +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/profile.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/profile.service.ts new file mode 100644 index 0000000000..d07fad7e7f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/profiles/profile.service.ts @@ -0,0 +1,40 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpResponse } from '@angular/common/http'; + +import { SERVER_API_URL } from 'app/app.constants'; +import { ProfileInfo } from './profile-info.model'; +import { map } from 'rxjs/operators'; + +@Injectable({ providedIn: 'root' }) +export class ProfileService { + private infoUrl = SERVER_API_URL + 'management/info'; + private profileInfo: Promise; + + constructor(private http: HttpClient) {} + + getProfileInfo(): Promise { + if (!this.profileInfo) { + this.profileInfo = this.http + .get(this.infoUrl, { observe: 'response' }) + .pipe( + map((res: HttpResponse) => { + const data = res.body; + const pi = new ProfileInfo(); + pi.activeProfiles = data['activeProfiles']; + const displayRibbonOnProfiles = data['display-ribbon-on-profiles'].split(','); + if (pi.activeProfiles) { + const ribbonProfiles = displayRibbonOnProfiles.filter(profile => pi.activeProfiles.includes(profile)); + if (ribbonProfiles.length !== 0) { + pi.ribbonEnv = ribbonProfiles[0]; + } + pi.inProduction = pi.activeProfiles.includes('prod'); + pi.swaggerEnabled = pi.activeProfiles.includes('swagger'); + } + return pi; + }) + ) + .toPromise(); + } + return this.profileInfo; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/polyfills.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/polyfills.ts new file mode 100644 index 0000000000..cf38f3221b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/polyfills.ts @@ -0,0 +1,70 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE9, IE10 and IE11 requires all of the following polyfills. **/ +import 'core-js/es6/symbol'; +import 'core-js/es6/object'; +import 'core-js/es6/function'; +import 'core-js/es6/parse-int'; +import 'core-js/es6/parse-float'; +import 'core-js/es6/number'; +import 'core-js/es6/math'; +import 'core-js/es6/string'; +import 'core-js/es6/date'; +import 'core-js/es6/array'; +import 'core-js/es7/array'; +import 'core-js/es6/regexp'; +import 'core-js/es6/map'; +import 'core-js/es6/weak-map'; +import 'core-js/es6/set'; + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** Evergreen browsers require these. **/ +import 'core-js/es6/reflect'; +import 'core-js/es7/reflect'; + +/** + * Required to support Web Animations `@angular/animation`. + * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation + **/ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/*************************************************************************************************** + * Zone JS is required by Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ + +/** + * Date, currency, decimal and percent pipes. + * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 + */ +// import 'intl'; // Run `npm install --save intl`. +/** + * Need to import at least one locale-data with intl. + */ +// import 'intl/locale-data/jsonp/en'; + +require('../manifest.webapp'); diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/alert/alert-error.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/alert/alert-error.component.ts new file mode 100644 index 0000000000..892e2d828c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/alert/alert-error.component.ts @@ -0,0 +1,110 @@ +import { Component, OnDestroy } from '@angular/core'; +import { JhiEventManager, JhiAlert, JhiAlertService } from 'ng-jhipster'; +import { Subscription } from 'rxjs'; + +@Component({ + selector: 'jhi-alert-error', + template: ` + + ` +}) +export class JhiAlertErrorComponent implements OnDestroy { + alerts: any[]; + cleanHttpErrorListener: Subscription; + /* tslint:disable */ + constructor(private alertService: JhiAlertService, private eventManager: JhiEventManager) { + /* tslint:enable */ + this.alerts = []; + + this.cleanHttpErrorListener = eventManager.subscribe('bookstoreApp.httpError', response => { + let i; + const httpErrorResponse = response.content; + switch (httpErrorResponse.status) { + // connection refused, server not reachable + case 0: + this.addErrorAlert('Server not reachable', 'error.server.not.reachable'); + break; + + case 400: + const arr = httpErrorResponse.headers.keys(); + let errorHeader = null; + let entityKey = null; + arr.forEach(entry => { + if (entry.toLowerCase().endsWith('app-error')) { + errorHeader = httpErrorResponse.headers.get(entry); + } else if (entry.toLowerCase().endsWith('app-params')) { + entityKey = httpErrorResponse.headers.get(entry); + } + }); + if (errorHeader) { + const entityName = entityKey; + this.addErrorAlert(errorHeader, errorHeader, { entityName }); + } else if (httpErrorResponse.error !== '' && httpErrorResponse.error.fieldErrors) { + const fieldErrors = httpErrorResponse.error.fieldErrors; + for (i = 0; i < fieldErrors.length; i++) { + const fieldError = fieldErrors[i]; + if (['Min', 'Max', 'DecimalMin', 'DecimalMax'].includes(fieldError.message)) { + fieldError.message = 'Size'; + } + // convert 'something[14].other[4].id' to 'something[].other[].id' so translations can be written to it + const convertedField = fieldError.field.replace(/\[\d*\]/g, '[]'); + const fieldName = convertedField.charAt(0).toUpperCase() + convertedField.slice(1); + this.addErrorAlert('Error on field "' + fieldName + '"', 'error.' + fieldError.message, { fieldName }); + } + } else if (httpErrorResponse.error !== '' && httpErrorResponse.error.message) { + this.addErrorAlert( + httpErrorResponse.error.message, + httpErrorResponse.error.message, + httpErrorResponse.error.params + ); + } else { + this.addErrorAlert(httpErrorResponse.error); + } + break; + + case 404: + this.addErrorAlert('Not found', 'error.url.not.found'); + break; + + default: + if (httpErrorResponse.error !== '' && httpErrorResponse.error.message) { + this.addErrorAlert(httpErrorResponse.error.message); + } else { + this.addErrorAlert(httpErrorResponse.error); + } + } + }); + } + + setClasses(alert) { + return { + toast: !!alert.toast, + [alert.position]: true + }; + } + + ngOnDestroy() { + if (this.cleanHttpErrorListener !== undefined && this.cleanHttpErrorListener !== null) { + this.eventManager.destroy(this.cleanHttpErrorListener); + this.alerts = []; + } + } + + addErrorAlert(message, key?, data?) { + const newAlert: JhiAlert = { + type: 'danger', + msg: message, + timeout: 5000, + toast: this.alertService.isToast(), + scoped: true + }; + + this.alerts.push(this.alertService.addAlert(newAlert, this.alerts)); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/alert/alert.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/alert/alert.component.ts new file mode 100644 index 0000000000..a77c3e72c5 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/alert/alert.component.ts @@ -0,0 +1,35 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { JhiAlertService } from 'ng-jhipster'; + +@Component({ + selector: 'jhi-alert', + template: ` + + ` +}) +export class JhiAlertComponent implements OnInit, OnDestroy { + alerts: any[]; + + constructor(private alertService: JhiAlertService) {} + + ngOnInit() { + this.alerts = this.alertService.get(); + } + + setClasses(alert) { + return { + toast: !!alert.toast, + [alert.position]: true + }; + } + + ngOnDestroy() { + this.alerts = []; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/auth/has-any-authority.directive.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/auth/has-any-authority.directive.ts new file mode 100644 index 0000000000..0f8cefb28e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/auth/has-any-authority.directive.ts @@ -0,0 +1,42 @@ +import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core'; +import { AccountService } from 'app/core/auth/account.service'; + +/** + * @whatItDoes Conditionally includes an HTML element if current user has any + * of the authorities passed as the `expression`. + * + * @howToUse + * ``` + * ... + * + * ... + * ``` + */ +@Directive({ + selector: '[jhiHasAnyAuthority]' +}) +export class HasAnyAuthorityDirective { + private authorities: string[]; + + constructor( + private accountService: AccountService, + private templateRef: TemplateRef, + private viewContainerRef: ViewContainerRef + ) {} + + @Input() + set jhiHasAnyAuthority(value: string | string[]) { + this.authorities = typeof value === 'string' ? [value] : value; + this.updateView(); + // Get notified each time authentication state changes. + this.accountService.getAuthenticationState().subscribe(identity => this.updateView()); + } + + private updateView(): void { + const hasAnyAuthority = this.accountService.hasAnyAuthority(this.authorities); + this.viewContainerRef.clear(); + if (hasAnyAuthority) { + this.viewContainerRef.createEmbeddedView(this.templateRef); + } + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/error.constants.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/error.constants.ts new file mode 100644 index 0000000000..2ebea94220 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/error.constants.ts @@ -0,0 +1,4 @@ +export const PROBLEM_BASE_URL = 'https://www.jhipster.tech/problem'; +export const EMAIL_ALREADY_USED_TYPE = PROBLEM_BASE_URL + '/email-already-used'; +export const LOGIN_ALREADY_USED_TYPE = PROBLEM_BASE_URL + '/login-already-used'; +export const EMAIL_NOT_FOUND_TYPE = PROBLEM_BASE_URL + '/email-not-found'; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/input.constants.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/input.constants.ts new file mode 100644 index 0000000000..1e3978a9b3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/input.constants.ts @@ -0,0 +1,2 @@ +export const DATE_FORMAT = 'YYYY-MM-DD'; +export const DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:mm'; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/pagination.constants.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/pagination.constants.ts new file mode 100644 index 0000000000..a148d4579b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/constants/pagination.constants.ts @@ -0,0 +1 @@ +export const ITEMS_PER_PAGE = 20; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/index.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/index.ts new file mode 100644 index 0000000000..92a8ccef73 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/index.ts @@ -0,0 +1,12 @@ +export * from './constants/error.constants'; +export * from './constants/pagination.constants'; +export * from './constants/input.constants'; +export * from './alert/alert.component'; +export * from './alert/alert-error.component'; +export * from './auth/has-any-authority.directive'; +export * from './login/login.component'; +export * from './util/request-util'; +export * from './shared-libs.module'; +export * from './shared-common.module'; +export * from './shared.module'; +export * from './util/datepicker-adapter'; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/login/login.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/login/login.component.html new file mode 100644 index 0000000000..60d593bd4b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/login/login.component.html @@ -0,0 +1,43 @@ + + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/login/login.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/login/login.component.ts new file mode 100644 index 0000000000..46711a0619 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/login/login.component.ts @@ -0,0 +1,87 @@ +import { Component, AfterViewInit, Renderer, ElementRef } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Router } from '@angular/router'; +import { JhiEventManager } from 'ng-jhipster'; + +import { LoginService } from 'app/core/login/login.service'; +import { StateStorageService } from 'app/core/auth/state-storage.service'; + +@Component({ + selector: 'jhi-login-modal', + templateUrl: './login.component.html' +}) +export class JhiLoginModalComponent implements AfterViewInit { + authenticationError: boolean; + password: string; + rememberMe: boolean; + username: string; + credentials: any; + + constructor( + private eventManager: JhiEventManager, + private loginService: LoginService, + private stateStorageService: StateStorageService, + private elementRef: ElementRef, + private renderer: Renderer, + private router: Router, + public activeModal: NgbActiveModal + ) { + this.credentials = {}; + } + + ngAfterViewInit() { + setTimeout(() => this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#username'), 'focus', []), 0); + } + + cancel() { + this.credentials = { + username: null, + password: null, + rememberMe: true + }; + this.authenticationError = false; + this.activeModal.dismiss('cancel'); + } + + login() { + this.loginService + .login({ + username: this.username, + password: this.password, + rememberMe: this.rememberMe + }) + .then(() => { + this.authenticationError = false; + this.activeModal.dismiss('login success'); + if (this.router.url === '/register' || /^\/activate\//.test(this.router.url) || /^\/reset\//.test(this.router.url)) { + this.router.navigate(['']); + } + + this.eventManager.broadcast({ + name: 'authenticationSuccess', + content: 'Sending Authentication Success' + }); + + // previousState was set in the authExpiredInterceptor before being redirected to login modal. + // since login is successful, go to stored previousState and clear previousState + const redirect = this.stateStorageService.getUrl(); + if (redirect) { + this.stateStorageService.storeUrl(null); + this.router.navigate([redirect]); + } + }) + .catch(() => { + this.authenticationError = true; + }); + } + + register() { + this.activeModal.dismiss('to state register'); + this.router.navigate(['/register']); + } + + requestResetPassword() { + this.activeModal.dismiss('to state requestReset'); + this.router.navigate(['/reset', 'request']); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared-common.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared-common.module.ts new file mode 100644 index 0000000000..c6e52d67c5 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared-common.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; + +import { BookstoreSharedLibsModule, JhiAlertComponent, JhiAlertErrorComponent } from './'; + +@NgModule({ + imports: [BookstoreSharedLibsModule], + declarations: [JhiAlertComponent, JhiAlertErrorComponent], + exports: [BookstoreSharedLibsModule, JhiAlertComponent, JhiAlertErrorComponent] +}) +export class BookstoreSharedCommonModule {} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared-libs.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared-libs.module.ts new file mode 100644 index 0000000000..79ac658edb --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared-libs.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { CommonModule } from '@angular/common'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { NgJhipsterModule } from 'ng-jhipster'; +import { InfiniteScrollModule } from 'ngx-infinite-scroll'; +import { CookieModule } from 'ngx-cookie'; +import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; + +@NgModule({ + imports: [NgbModule.forRoot(), InfiniteScrollModule, CookieModule.forRoot(), FontAwesomeModule], + exports: [FormsModule, CommonModule, NgbModule, NgJhipsterModule, InfiniteScrollModule, FontAwesomeModule] +}) +export class BookstoreSharedLibsModule { + static forRoot() { + return { + ngModule: BookstoreSharedLibsModule + }; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared.module.ts new file mode 100644 index 0000000000..695b166793 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/shared.module.ts @@ -0,0 +1,21 @@ +import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { NgbDateAdapter } from '@ng-bootstrap/ng-bootstrap'; + +import { NgbDateMomentAdapter } from './util/datepicker-adapter'; +import { BookstoreSharedLibsModule, BookstoreSharedCommonModule, JhiLoginModalComponent, HasAnyAuthorityDirective } from './'; + +@NgModule({ + imports: [BookstoreSharedLibsModule, BookstoreSharedCommonModule], + declarations: [JhiLoginModalComponent, HasAnyAuthorityDirective], + providers: [{ provide: NgbDateAdapter, useClass: NgbDateMomentAdapter }], + entryComponents: [JhiLoginModalComponent], + exports: [BookstoreSharedCommonModule, JhiLoginModalComponent, HasAnyAuthorityDirective], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BookstoreSharedModule { + static forRoot() { + return { + ngModule: BookstoreSharedModule + }; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/util/datepicker-adapter.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/util/datepicker-adapter.ts new file mode 100644 index 0000000000..524a38c834 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/util/datepicker-adapter.ts @@ -0,0 +1,21 @@ +/** + * Angular bootstrap Date adapter + */ +import { Injectable } from '@angular/core'; +import { NgbDateAdapter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap'; +import { Moment } from 'moment'; +import * as moment from 'moment'; + +@Injectable() +export class NgbDateMomentAdapter extends NgbDateAdapter { + fromModel(date: Moment): NgbDateStruct { + if (date != null && moment.isMoment(date) && date.isValid()) { + return { year: date.year(), month: date.month() + 1, day: date.date() }; + } + return null; + } + + toModel(date: NgbDateStruct): Moment { + return date ? moment(date.year + '-' + date.month + '-' + date.day, 'YYYY-MM-DD') : null; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/util/request-util.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/util/request-util.ts new file mode 100644 index 0000000000..6579c3cb2a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/util/request-util.ts @@ -0,0 +1,18 @@ +import { HttpParams } from '@angular/common/http'; + +export const createRequestOption = (req?: any): HttpParams => { + let options: HttpParams = new HttpParams(); + if (req) { + Object.keys(req).forEach(key => { + if (key !== 'sort') { + options = options.set(key, req[key]); + } + }); + if (req.sort) { + req.sort.forEach(val => { + options = options.append('sort', val); + }); + } + } + return options; +}; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/vendor.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/vendor.ts new file mode 100644 index 0000000000..e8923d5c66 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/vendor.ts @@ -0,0 +1,81 @@ +/* after changing this file run 'npm run webpack:build' */ +/* tslint:disable */ +import '../content/scss/vendor.scss'; + +// Imports all fontawesome core and solid icons + +import { library } from '@fortawesome/fontawesome-svg-core'; +import { + faUser, + faSort, + faSortUp, + faSortDown, + faSync, + faEye, + faBan, + faTimes, + faArrowLeft, + faSave, + faPlus, + faPencilAlt, + faBars, + faThList, + faUserPlus, + faRoad, + faTachometerAlt, + faHeart, + faList, + faBell, + faBook, + faHdd, + faFlag, + faWrench, + faClock, + faCloud, + faSignOutAlt, + faSignInAlt, + faCalendarAlt, + faSearch, + faTrashAlt, + faAsterisk, + faTasks, + faHome +} from '@fortawesome/free-solid-svg-icons'; + +// Adds the SVG icon to the library so you can use it in your page +library.add(faUser); +library.add(faSort); +library.add(faSortUp); +library.add(faSortDown); +library.add(faSync); +library.add(faEye); +library.add(faBan); +library.add(faTimes); +library.add(faArrowLeft); +library.add(faSave); +library.add(faPlus); +library.add(faPencilAlt); +library.add(faBars); +library.add(faHome); +library.add(faThList); +library.add(faUserPlus); +library.add(faRoad); +library.add(faTachometerAlt); +library.add(faHeart); +library.add(faList); +library.add(faBell); +library.add(faTasks); +library.add(faBook); +library.add(faHdd); +library.add(faFlag); +library.add(faWrench); +library.add(faClock); +library.add(faCloud); +library.add(faSignOutAlt); +library.add(faSignInAlt); +library.add(faCalendarAlt); +library.add(faSearch); +library.add(faTrashAlt); +library.add(faAsterisk); + +// jhipster-needle-add-element-to-vendor - JHipster will add new menu items here diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/css/loading.css b/jhipster-5/bookstore-monolith/src/main/webapp/content/css/loading.css new file mode 100644 index 0000000000..a1e24615b4 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/content/css/loading.css @@ -0,0 +1,152 @@ +@keyframes lds-pacman-1 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 50% { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + } + 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } +} +@-webkit-keyframes lds-pacman-1 { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 50% { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + } + 100% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } +} +@keyframes lds-pacman-2 { + 0% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); + } + 50% { + -webkit-transform: rotate(225deg); + transform: rotate(225deg); + } + 100% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); + } +} +@-webkit-keyframes lds-pacman-2 { + 0% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); + } + 50% { + -webkit-transform: rotate(225deg); + transform: rotate(225deg); + } + 100% { + -webkit-transform: rotate(180deg); + transform: rotate(180deg); + } +} +@keyframes lds-pacman-3 { + 0% { + -webkit-transform: translate(190px, 0); + transform: translate(190px, 0); + opacity: 0; + } + 20% { + opacity: 1; + } + 100% { + -webkit-transform: translate(70px, 0); + transform: translate(70px, 0); + opacity: 1; + } +} +@-webkit-keyframes lds-pacman-3 { + 0% { + -webkit-transform: translate(190px, 0); + transform: translate(190px, 0); + opacity: 0; + } + 20% { + opacity: 1; + } + 100% { + -webkit-transform: translate(70px, 0); + transform: translate(70px, 0); + opacity: 1; + } +} + +.app-loading { + font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + top: 10em; +} +.app-loading p { + display: block; + font-size: 1.17em; + margin-inline-start: 0px; + margin-inline-end: 0px; + font-weight: normal; +} + +.app-loading .lds-pacman { + position: relative; + margin: auto; + width: 200px !important; + height: 200px !important; + -webkit-transform: translate(-100px, -100px) scale(1) translate(100px, 100px); + transform: translate(-100px, -100px) scale(1) translate(100px, 100px); +} +.app-loading .lds-pacman > div:nth-child(2) div { + position: absolute; + top: 40px; + left: 40px; + width: 120px; + height: 60px; + border-radius: 120px 120px 0 0; + background: #bbcedd; + -webkit-animation: lds-pacman-1 1s linear infinite; + animation: lds-pacman-1 1s linear infinite; + -webkit-transform-origin: 60px 60px; + transform-origin: 60px 60px; +} +.app-loading .lds-pacman > div:nth-child(2) div:nth-child(2) { + -webkit-animation: lds-pacman-2 1s linear infinite; + animation: lds-pacman-2 1s linear infinite; +} +.app-loading .lds-pacman > div:nth-child(1) div { + position: absolute; + top: 97px; + left: -8px; + width: 24px; + height: 10px; + background-image: url('../images/logo-jhipster.png'); + background-size: contain; + -webkit-animation: lds-pacman-3 1s linear infinite; + animation: lds-pacman-3 1.5s linear infinite; +} +.app-loading .lds-pacman > div:nth-child(1) div:nth-child(1) { + -webkit-animation-delay: -0.67s; + animation-delay: -1s; +} +.app-loading .lds-pacman > div:nth-child(1) div:nth-child(2) { + -webkit-animation-delay: -0.33s; + animation-delay: -0.5s; +} +.app-loading .lds-pacman > div:nth-child(1) div:nth-child(3) { + -webkit-animation-delay: 0s; + animation-delay: 0s; +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0.svg b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0.svg new file mode 100755 index 0000000000..1f9ab52790 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0.svg @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-192.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-192.png new file mode 100644 index 0000000000000000000000000000000000000000..81330689211e5a082081222dcaf30c37ea6104cf GIT binary patch literal 13322 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 E2c#yGumAu6 literal 0 HcmV?d00001 diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-256.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_0_head-256.png new file mode 100644 index 0000000000000000000000000000000000000000..b4739ec3e47edbc81542888fd0fe7f9bb411c5b1 GIT binary patch literal 17812 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 literal 0 HcmV?d00001 diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1.svg b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1.svg new file mode 100755 index 0000000000..7a118f3077 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1.svg @@ -0,0 +1,9387 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-192.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-192.png new file mode 100644 index 0000000000000000000000000000000000000000..dd2643c15dd3055d1ca3fc057e0e4f7b0b93b785 GIT binary patch literal 19660 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 literal 0 HcmV?d00001 diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-384.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-384.png new file mode 100644 index 0000000000000000000000000000000000000000..f930681c128095fb436ebc8b486e94baf6cfc186 GIT binary patch literal 48895 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 UO0?Ay3<5r~Qi_t*;zl9=2eGOgGynhq literal 0 HcmV?d00001 diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-512.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_1_head-512.png new file mode 100644 index 0000000000000000000000000000000000000000..9110dc8fe44bf6ed248a2723f15e900d87cec9a8 GIT binary patch literal 68803 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

Wv|Q)i4zQT>0V0j?|=lCiv9> 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 l0H^_Ab#1lF#l^+?e*r!59D4!FVj} + + +image/svg+xml \ No newline at end of file diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-192.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-192.png new file mode 100644 index 0000000000000000000000000000000000000000..2699ab447391d7a1dfb0fceb9f47e30183a731f9 GIT binary patch literal 11463 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 literal 0 HcmV?d00001 diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-384.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-384.png new file mode 100644 index 0000000000000000000000000000000000000000..da964fcb2e387f81a934f2dc669462aa4a6c85ea GIT binary patch literal 23850 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 literal 0 HcmV?d00001 diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-512.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_2_head-512.png new file mode 100644 index 0000000000000000000000000000000000000000..6337f5effb4ae653bf2daa4af71df885205dbd72 GIT binary patch literal 32300 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-192.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-192.png new file mode 100644 index 0000000000000000000000000000000000000000..35b91257fcce7a1664efa2979af2fa4ee4afb97a GIT binary patch literal 13573 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 LNkvXXu0mjfv2Czq literal 0 HcmV?d00001 diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-256.png b/jhipster-5/bookstore-monolith/src/main/webapp/content/images/jhipster_family_member_3_head-256.png new file mode 100644 index 0000000000000000000000000000000000000000..098fd8fb05ae1f40a2ad8cef4547c2cae2adda83 GIT binary patch literal 19239 zcmV*pKt{ibP)`1aL%Tg?hqDfhW7Da*(MN$$QSOkJ3DhVvw z_UUuWIr(E2Wq10_otXuJ_j&M;d&@cB&VF;scfKMxPeqPyTR2bo)-@W|3iL`eD}hxS zA_4{g0rUe!Ag5s*$O#zNnu8L3P$S;dLLbnkcyZbNhsS#O>zs9nUJEc=IC970s5XuF zBlJ7bTnAhnY!CXNM!W#x1u6K!xRLzPhWmFp!S?a?;ha`XeIN43D~o?hDC6ff`fec6 zwax`ut$6|=9+SfV_TmSQyweK@jLP5e?xFtuVtCyRRs47p}u-vN#BNw zdEggThQn#KT4}FeYcU`N18AWX+L1zdS}O(eH-Kw;Eo(KD)<027|GncD{%Y;RW2s)t z(+kdO#nd-r4h<~10_0Cg^fe0B30MipsxJw4qG!!0Sre@_j^~XO3eGdW@*bC3KfK}b z%&uO`)eX)%#nks9hhAKAixl$Yx-i*f3$KH?s3XF45XW`N7YZm}9aLIBqzv(wmp+z$ zqt|kEinB&B5B$Q)u$}V%73g0>v#RBWENcSS?GI42uHrZj`9cw2DXrnVX!WO?cVr*! zwOm0n>lIVqhdlDqvR@GBKhUtK-S&hXMmvQdMC%<|Q*cTnsMZ<~k80olcblKczS3*a zf?`%H=CQk%ZS>H8BjAdl+7zaV_Pn5)>nTbp@`VCL#|7|&=1&Ug^zUwc9=F%Bwactj zObz15Jxf1>=Dz{qKpPhVv<|e%UgLNk*<2p26u@)7HDNJ8MMZeLceRn_RRJ!b=@{SSIonAFZ(Nj{#38!I1>%Hu8Zq> zxUL66V;Ba8G?0eGloBZor0n^}R~OIoNM&+>9z)10H*KHX*K3&?p{Jkhk-L|ESi_fl zDZ^g2*(Kj9X(b`nEF

+u_yv@`A>EvKGth_YSGo< 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 DEYbKo literal 0 HcmV?d00001 diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/scss/_bootstrap-variables.scss b/jhipster-5/bookstore-monolith/src/main/webapp/content/scss/_bootstrap-variables.scss new file mode 100644 index 0000000000..be0f226497 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/content/scss/_bootstrap-variables.scss @@ -0,0 +1,42 @@ +/* +* Bootstrap overrides https://getbootstrap.com/docs/4.0/getting-started/theming/ +* All values defined in bootstrap source +* https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss can be overwritten here +* Make sure not to add !default to values here +*/ + +// Colors: +// Grayscale and brand colors for use across Bootstrap. + +$primary: #3e8acc; +$success: #28a745; +$info: #17a2b8; +$warning: #ffc107; +$danger: #dc3545; + +// Options: +// Quickly modify global styling by enabling or disabling optional features. +$enable-rounded: true; +$enable-shadows: false; +$enable-gradients: false; +$enable-transitions: true; +$enable-hover-media-query: false; +$enable-grid-classes: true; +$enable-print-styles: true; + +// Components: +// Define common padding and border radius sizes and more. + +$border-radius: 0.15rem; +$border-radius-lg: 0.125rem; +$border-radius-sm: 0.1rem; + +// Body: +// Settings for the `` element. + +$body-bg: #e4e5e6; + +// Typography: +// Font, line-height, and color for body text, headings, and more. + +$font-size-base: 1rem; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/scss/global.scss b/jhipster-5/bookstore-monolith/src/main/webapp/content/scss/global.scss new file mode 100644 index 0000000000..cfbb9bf5b8 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/content/scss/global.scss @@ -0,0 +1,226 @@ +@import 'bootstrap-variables'; + +/* ============================================================== +Bootstrap tweaks +===============================================================*/ + +body, +h1, +h2, +h3, +h4 { + font-weight: 300; +} + +a { + color: #533f03; + font-weight: bold; +} + +a:hover { + color: #533f03; + font-weight: bold; + /* make sure browsers use the pointer cursor for anchors, even with no href */ + cursor: pointer; +} + +/* ========================================================================== +Browser Upgrade Prompt +========================================================================== */ +.browserupgrade { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +/* ========================================================================== +Generic styles +========================================================================== */ + +/* Error highlight on input fields */ +.ng-valid[required], +.ng-valid.required { + border-left: 5px solid green; +} + +.ng-invalid:not(form) { + border-left: 5px solid red; +} + +/* other generic styles */ + +.jh-card { + padding: 1.5%; + margin-top: 20px; + border: none; +} + +.error { + color: white; + background-color: red; +} + +.pad { + padding: 10px; +} + +.w-40 { + width: 40% !important; +} + +.w-60 { + width: 60% !important; +} + +.break { + white-space: normal; + word-break: break-all; +} + +.readonly { + background-color: #eee; + opacity: 1; +} + +.footer { + border-top: 1px solid rgba(0, 0, 0, 0.125); +} + +.hand, +[jhisortby] { + cursor: pointer; +} + +/* ========================================================================== +Custom alerts for notification +========================================================================== */ +.alerts { + .alert { + text-overflow: ellipsis; + pre { + background: none; + border: none; + font: inherit; + color: inherit; + padding: 0; + margin: 0; + } + .popover pre { + font-size: 10px; + } + } + .toast { + position: fixed; + width: 100%; + &.left { + left: 5px; + } + &.right { + right: 5px; + } + &.top { + top: 55px; + } + &.bottom { + bottom: 55px; + } + } +} + +@media screen and (min-width: 480px) { + .alerts .toast { + width: 50%; + } +} + +/* ========================================================================== +entity tables helpers +========================================================================== */ + +/* Remove Bootstrap padding from the element +http://stackoverflow.com/questions/19562903/remove-padding-from-columns-in-bootstrap-3 */ +@mixin no-padding($side) { + @if $side == 'all' { + .no-padding { + padding: 0 !important; + } + } @else { + .no-padding-#{$side} { + padding-#{$side}: 0 !important; + } + } +} +@include no-padding('left'); +@include no-padding('right'); +@include no-padding('top'); +@include no-padding('bottom'); +@include no-padding('all'); + +/* bootstrap 3 input-group 100% width +http://stackoverflow.com/questions/23436430/bootstrap-3-input-group-100-width */ +.width-min { + width: 1% !important; +} + +/* Makes toolbar not wrap on smaller screens +http://www.sketchingwithcss.com/samplechapter/cheatsheet.html#right */ +.flex-btn-group-container { + display: -webkit-flex; + display: flex; + -webkit-flex-direction: row; + flex-direction: row; + -webkit-justify-content: flex-end; + justify-content: flex-end; +} + +/* ========================================================================== +entity detail page css +========================================================================== */ +.row.jh-entity-details > { + dd { + margin-bottom: 15px; + } +} + +@media screen and (min-width: 768px) { + .row.jh-entity-details > { + dt { + margin-bottom: 15px; + } + dd { + border-bottom: 1px solid #eee; + padding-left: 180px; + margin-left: 0; + } + } +} + +/* ========================================================================== +ui bootstrap tweaks +========================================================================== */ +.nav, +.pagination, +.carousel, +.panel-title a { + cursor: pointer; +} + +.datetime-picker-dropdown > li.date-picker-menu div > table .btn-default, +.uib-datepicker-popup > li > div.uib-datepicker > table .btn-default { + border: 0; +} + +.datetime-picker-dropdown > li.date-picker-menu div > table:focus, +.uib-datepicker-popup > li > div.uib-datepicker > table:focus { + outline: none; +} + +.thread-dump-modal-lock { + max-width: 450px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* jhipster-needle-scss-add-main JHipster will add new css style */ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/content/scss/vendor.scss b/jhipster-5/bookstore-monolith/src/main/webapp/content/scss/vendor.scss new file mode 100644 index 0000000000..12a8f54b83 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/content/scss/vendor.scss @@ -0,0 +1,12 @@ +/* after changing this file run 'npm run webpack:build' */ + +/*************************** +put Sass variables here: +eg $input-color: red; +****************************/ +// Override Boostrap variables +@import 'bootstrap-variables'; +// Import Bootstrap source files from node_modules +@import '~bootstrap/scss/bootstrap'; + +/* jhipster-needle-scss-add-vendor JHipster will add new css style */ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/favicon.ico b/jhipster-5/bookstore-monolith/src/main/webapp/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..4179874f53b3c3b0ba9e2a401412f814ab6296bd GIT binary patch literal 1574 zcmV+>2HE+EP)000H;Nkl9r4a2J+cS@yzSX6E!^*k!$-D-4;C?DsI4Z2te8^PT@c z=RfD)VMK(b3{GnU7K#)Bt&t+2HBtn$Mv8#eNDUS>&~)z8>N1c(q8rNd{sPjn1MM2QHDA^sG2W;HKsEVpi{%G+8~m}54A zpq~8zXet!#9Gbj-*V8>RHQ@_Oa=ck5fDynmyijTRbXS$xsGFssxLtW3`my8G-!>%7 zn;n<%&U37xG-qc+$&NL}Ic8(r8P8{L>@pz`5wF~FxA(hl3{Q#@0mJ|T!>orWW&$y= zwZ)lV?q9=mOj&=001@Fo=j2<5|CsUovve~87<4?ht)^g4)54xHIM_fH6g9vTH~{$6e3n@@!>>0A((rb8tLK5s#V0 zMm+wn&))p*T>q|hCGR#@SL9}ZK#Tw|V#*5$4}y`?UCz_p4!1wNkO1l#@e&9G#+VYs zEG&vW!|wTsW3iPFM8p#vgQq%eFRm{7prxk1*aAS&G~ti@^w-GQ9%mpd0W^=8Nrc@q z?FmG(O?n~{0D#CgKIQg@lG#5`2LTaLZtu09`*&npbwOKeU4B;jv8(n!ddI?|{BT~F zzml*h^*el9D=mnp(SK|%RkC6{JP5dS>;C22j@;ZLQI=y-twP>a1a%F2w^mvhW1N!C zItRzq%;^AP-WFw5y#6R|j(8Qh9Dt}K_u4&+p(d6Y7r5u2fMIuVYB~yqz^KPR<_)T> zVUZCQ2K>q>IWj4>kGx1p%HD(9OEwu=KUlGU-EF%U2| z6%r-`VTl%YwkK@x(j4)7%q9E||Yz*Vu z-KgXDY^wP1l~c9KAAp;kIku<%ZR4V3H)gcci^L zxuYQ7iwPXJy}sz+_S%}ltQn(|jw6aU+5iCCMBw-}`=x=2s3a#J7eur?P5(n%lfW3; zzojxs0t_(d_}%ME4>VV=%*&kl@mY?4RLIPDrr1%QWBTmX>U-{zUphzI`^LkPoTQkY z^?7=MW3nvEM4$hB{Zyw7M3hi@DgLIIc}3Z#J)0`_Hm$Unjj=qofc>keP`dJ1mj{ks?4R(3kPwGF$MQ4Nw$&8u zY$#b@Zsp>+MfD;l;gbiMsB74J{+6r5=JEI=N`S;Tl0o2i)aJImRADmkV6kfzMM5Yl zb`4GR+C9Ed)T9?ySkhM)WtCdZJg310p5oRacks5uH}YWG9~KQdzS3&iP?nXGu8&`< zB@h73l>ryEsGJ*5{SM`E0!tK2{&F`(Kx?E3XpIyBt&t+2HBtn$Mv8#eND + + + + + + Bookstore + + + + + + + + + + + +

+ + + + + + + + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/manifest.webapp b/jhipster-5/bookstore-monolith/src/main/webapp/manifest.webapp new file mode 100644 index 0000000000..42b606ea1d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/manifest.webapp @@ -0,0 +1,31 @@ +{ + "name": "Bookstore", + "short_name": "Bookstore", + "icons": [ + { + "src": "./content/images/jhipster_family_member_0_head-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "./content/images/jhipster_family_member_0_head-256.png", + "sizes": "256x256", + "type": "image/png" + }, + { + "src": "./content/images/jhipster_family_member_0_head-384.png", + "sizes": "384x384", + "type": "image/png" + }, + { + "src": "./content/images/jhipster_family_member_0_head-512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#000000", + "background_color": "#e0e0e0", + "start_url": "/index.html", + "display": "standalone", + "orientation": "portrait" +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/robots.txt b/jhipster-5/bookstore-monolith/src/main/webapp/robots.txt new file mode 100644 index 0000000000..7cda27477d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/robots.txt @@ -0,0 +1,11 @@ +# robotstxt.org/ + +User-agent: * +Disallow: /api/account +Disallow: /api/account/change-password +Disallow: /api/account/sessions +Disallow: /api/audits/ +Disallow: /api/logs/ +Disallow: /api/users/ +Disallow: /management/ +Disallow: /v2/api-docs/ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/swagger-ui/index.html b/jhipster-5/bookstore-monolith/src/main/webapp/swagger-ui/index.html new file mode 100644 index 0000000000..416eacef70 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/swagger-ui/index.html @@ -0,0 +1,166 @@ + + + + + Swagger UI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+
+ + diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/WebConfigurerTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/WebConfigurerTest.java new file mode 100644 index 0000000000..670042d2df --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/WebConfigurerTest.java @@ -0,0 +1,189 @@ +package com.baeldung.jhipster5.config; + +import io.github.jhipster.config.JHipsterConstants; +import io.github.jhipster.config.JHipsterProperties; +import io.github.jhipster.web.filter.CachingHttpHeadersFilter; +import io.undertow.Undertow; +import io.undertow.Undertow.Builder; +import io.undertow.UndertowOptions; +import org.apache.commons.io.FilenameUtils; + +import org.h2.server.web.WebServlet; +import org.junit.Before; +import org.junit.Test; +import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.mock.env.MockEnvironment; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.xnio.OptionMap; + +import javax.servlet.*; +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * Unit tests for the WebConfigurer class. + * + * @see WebConfigurer + */ +public class WebConfigurerTest { + + private WebConfigurer webConfigurer; + + private MockServletContext servletContext; + + private MockEnvironment env; + + private JHipsterProperties props; + + @Before + public void setup() { + servletContext = spy(new MockServletContext()); + doReturn(mock(FilterRegistration.Dynamic.class)) + .when(servletContext).addFilter(anyString(), any(Filter.class)); + doReturn(mock(ServletRegistration.Dynamic.class)) + .when(servletContext).addServlet(anyString(), any(Servlet.class)); + + env = new MockEnvironment(); + props = new JHipsterProperties(); + + webConfigurer = new WebConfigurer(env, props); + } + + @Test + public void testStartUpProdServletContext() throws ServletException { + env.setActiveProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION); + webConfigurer.onStartup(servletContext); + + verify(servletContext).addFilter(eq("cachingHttpHeadersFilter"), any(CachingHttpHeadersFilter.class)); + verify(servletContext, never()).addServlet(eq("H2Console"), any(WebServlet.class)); + } + + @Test + public void testStartUpDevServletContext() throws ServletException { + env.setActiveProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT); + webConfigurer.onStartup(servletContext); + + verify(servletContext, never()).addFilter(eq("cachingHttpHeadersFilter"), any(CachingHttpHeadersFilter.class)); + verify(servletContext).addServlet(eq("H2Console"), any(WebServlet.class)); + } + + @Test + public void testCustomizeServletContainer() { + env.setActiveProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION); + UndertowServletWebServerFactory container = new UndertowServletWebServerFactory(); + webConfigurer.customize(container); + assertThat(container.getMimeMappings().get("abs")).isEqualTo("audio/x-mpeg"); + assertThat(container.getMimeMappings().get("html")).isEqualTo("text/html;charset=utf-8"); + assertThat(container.getMimeMappings().get("json")).isEqualTo("text/html;charset=utf-8"); + if (container.getDocumentRoot() != null) { + assertThat(container.getDocumentRoot().getPath()).isEqualTo(FilenameUtils.separatorsToSystem("target/www")); + } + + Builder builder = Undertow.builder(); + container.getBuilderCustomizers().forEach(c -> c.customize(builder)); + OptionMap.Builder serverOptions = (OptionMap.Builder) ReflectionTestUtils.getField(builder, "serverOptions"); + assertThat(serverOptions.getMap().get(UndertowOptions.ENABLE_HTTP2)).isNull(); + } + + @Test + public void testUndertowHttp2Enabled() { + props.getHttp().setVersion(JHipsterProperties.Http.Version.V_2_0); + UndertowServletWebServerFactory container = new UndertowServletWebServerFactory(); + webConfigurer.customize(container); + Builder builder = Undertow.builder(); + container.getBuilderCustomizers().forEach(c -> c.customize(builder)); + OptionMap.Builder serverOptions = (OptionMap.Builder) ReflectionTestUtils.getField(builder, "serverOptions"); + assertThat(serverOptions.getMap().get(UndertowOptions.ENABLE_HTTP2)).isTrue(); + } + + @Test + public void testCorsFilterOnApiPath() throws Exception { + props.getCors().setAllowedOrigins(Collections.singletonList("*")); + props.getCors().setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); + props.getCors().setAllowedHeaders(Collections.singletonList("*")); + props.getCors().setMaxAge(1800L); + props.getCors().setAllowCredentials(true); + + MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()) + .addFilters(webConfigurer.corsFilter()) + .build(); + + mockMvc.perform( + options("/api/test-cors") + .header(HttpHeaders.ORIGIN, "other.domain.com") + .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST")) + .andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "other.domain.com")) + .andExpect(header().string(HttpHeaders.VARY, "Origin")) + .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,PUT,DELETE")) + .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true")) + .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800")); + + mockMvc.perform( + get("/api/test-cors") + .header(HttpHeaders.ORIGIN, "other.domain.com")) + .andExpect(status().isOk()) + .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "other.domain.com")); + } + + @Test + public void testCorsFilterOnOtherPath() throws Exception { + props.getCors().setAllowedOrigins(Collections.singletonList("*")); + props.getCors().setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); + props.getCors().setAllowedHeaders(Collections.singletonList("*")); + props.getCors().setMaxAge(1800L); + props.getCors().setAllowCredentials(true); + + MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()) + .addFilters(webConfigurer.corsFilter()) + .build(); + + mockMvc.perform( + get("/test/test-cors") + .header(HttpHeaders.ORIGIN, "other.domain.com")) + .andExpect(status().isOk()) + .andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + } + + @Test + public void testCorsFilterDeactivated() throws Exception { + props.getCors().setAllowedOrigins(null); + + MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()) + .addFilters(webConfigurer.corsFilter()) + .build(); + + mockMvc.perform( + get("/api/test-cors") + .header(HttpHeaders.ORIGIN, "other.domain.com")) + .andExpect(status().isOk()) + .andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + } + + @Test + public void testCorsFilterDeactivated2() throws Exception { + props.getCors().setAllowedOrigins(new ArrayList<>()); + + MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()) + .addFilters(webConfigurer.corsFilter()) + .build(); + + mockMvc.perform( + get("/api/test-cors") + .header(HttpHeaders.ORIGIN, "other.domain.com")) + .andExpect(status().isOk()) + .andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/WebConfigurerTestController.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/WebConfigurerTestController.java new file mode 100644 index 0000000000..c19b28ea16 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/WebConfigurerTestController.java @@ -0,0 +1,16 @@ +package com.baeldung.jhipster5.config; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class WebConfigurerTestController { + + @GetMapping("/api/test-cors") + public void testCorsOnApiPath() { + } + + @GetMapping("/test/test-cors") + public void testCorsOnOtherPath() { + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/timezone/HibernateTimeZoneTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/timezone/HibernateTimeZoneTest.java new file mode 100644 index 0000000000..9027606e67 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/config/timezone/HibernateTimeZoneTest.java @@ -0,0 +1,176 @@ +package com.baeldung.jhipster5.config.timezone; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.repository.timezone.DateTimeWrapper; +import com.baeldung.jhipster5.repository.timezone.DateTimeWrapperRepository; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.rowset.SqlRowSet; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.time.*; +import java.time.format.DateTimeFormatter; + +import static java.lang.String.format; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Unit tests for the UTC Hibernate configuration. + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +public class HibernateTimeZoneTest { + + @Autowired + private DateTimeWrapperRepository dateTimeWrapperRepository; + @Autowired + private JdbcTemplate jdbcTemplate; + + private DateTimeWrapper dateTimeWrapper; + private DateTimeFormatter dateTimeFormatter; + private DateTimeFormatter timeFormatter; + private DateTimeFormatter dateFormatter; + + @Before + public void setup() { + dateTimeWrapper = new DateTimeWrapper(); + dateTimeWrapper.setInstant(Instant.parse("2014-11-12T05:50:00.0Z")); + dateTimeWrapper.setLocalDateTime(LocalDateTime.parse("2014-11-12T07:50:00.0")); + dateTimeWrapper.setOffsetDateTime(OffsetDateTime.parse("2011-12-14T08:30:00.0Z")); + dateTimeWrapper.setZonedDateTime(ZonedDateTime.parse("2011-12-14T08:30:00.0Z")); + dateTimeWrapper.setLocalTime(LocalTime.parse("14:30:00")); + dateTimeWrapper.setOffsetTime(OffsetTime.parse("14:30:00+02:00")); + dateTimeWrapper.setLocalDate(LocalDate.parse("2016-09-10")); + + dateTimeFormatter = DateTimeFormatter + .ofPattern("yyyy-MM-dd HH:mm:ss.S") + .withZone(ZoneId.of("UTC")); + + timeFormatter = DateTimeFormatter + .ofPattern("HH:mm:ss") + .withZone(ZoneId.of("UTC")); + + dateFormatter = DateTimeFormatter + .ofPattern("yyyy-MM-dd"); + } + + @Test + @Transactional + public void storeInstantWithUtcConfigShouldBeStoredOnGMTTimeZone() { + dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); + + String request = generateSqlRequest("instant", dateTimeWrapper.getId()); + SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); + String expectedValue = dateTimeFormatter.format(dateTimeWrapper.getInstant()); + + assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); + } + + @Test + @Transactional + public void storeLocalDateTimeWithUtcConfigShouldBeStoredOnGMTTimeZone() { + dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); + + String request = generateSqlRequest("local_date_time", dateTimeWrapper.getId()); + SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); + String expectedValue = dateTimeWrapper + .getLocalDateTime() + .atZone(ZoneId.systemDefault()) + .format(dateTimeFormatter); + + assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); + } + + @Test + @Transactional + public void storeOffsetDateTimeWithUtcConfigShouldBeStoredOnGMTTimeZone() { + dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); + + String request = generateSqlRequest("offset_date_time", dateTimeWrapper.getId()); + SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); + String expectedValue = dateTimeWrapper + .getOffsetDateTime() + .format(dateTimeFormatter); + + assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); + } + + @Test + @Transactional + public void storeZoneDateTimeWithUtcConfigShouldBeStoredOnGMTTimeZone() { + dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); + + String request = generateSqlRequest("zoned_date_time", dateTimeWrapper.getId()); + SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); + String expectedValue = dateTimeWrapper + .getZonedDateTime() + .format(dateTimeFormatter); + + assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); + } + + @Test + @Transactional + public void storeLocalTimeWithUtcConfigShouldBeStoredOnGMTTimeZoneAccordingToHis1stJan1970Value() { + dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); + + String request = generateSqlRequest("local_time", dateTimeWrapper.getId()); + SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); + String expectedValue = dateTimeWrapper + .getLocalTime() + .atDate(LocalDate.of(1970, Month.JANUARY, 1)) + .atZone(ZoneId.systemDefault()) + .format(timeFormatter); + + assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); + } + + @Test + @Transactional + public void storeOffsetTimeWithUtcConfigShouldBeStoredOnGMTTimeZoneAccordingToHis1stJan1970Value() { + dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); + + String request = generateSqlRequest("offset_time", dateTimeWrapper.getId()); + SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); + String expectedValue = dateTimeWrapper + .getOffsetTime() + .toLocalTime() + .atDate(LocalDate.of(1970, Month.JANUARY, 1)) + .atZone(ZoneId.systemDefault()) + .format(timeFormatter); + + assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); + } + + @Test + @Transactional + public void storeLocalDateWithUtcConfigShouldBeStoredWithoutTransformation() { + dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); + + String request = generateSqlRequest("local_date", dateTimeWrapper.getId()); + SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); + String expectedValue = dateTimeWrapper + .getLocalDate() + .format(dateFormatter); + + assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); + } + + private String generateSqlRequest(String fieldName, long id) { + return format("SELECT %s FROM jhi_date_time_wrapper where id=%d", fieldName, id); + } + + private void assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(SqlRowSet sqlRowSet, String expectedValue) { + while (sqlRowSet.next()) { + String dbValue = sqlRowSet.getString(1); + + assertThat(dbValue).isNotNull(); + assertThat(dbValue).isEqualTo(expectedValue); + } + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/CustomAuditEventRepositoryIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/CustomAuditEventRepositoryIntTest.java new file mode 100644 index 0000000000..eaf5c07504 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/CustomAuditEventRepositoryIntTest.java @@ -0,0 +1,165 @@ +package com.baeldung.jhipster5.repository; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.config.Constants; +import com.baeldung.jhipster5.config.audit.AuditEventConverter; +import com.baeldung.jhipster5.domain.PersistentAuditEvent; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.audit.AuditEvent; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpSession; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static com.baeldung.jhipster5.repository.CustomAuditEventRepository.EVENT_DATA_COLUMN_MAX_LENGTH; + +/** + * Test class for the CustomAuditEventRepository class. + * + * @see CustomAuditEventRepository + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +@Transactional +public class CustomAuditEventRepositoryIntTest { + + @Autowired + private PersistenceAuditEventRepository persistenceAuditEventRepository; + + @Autowired + private AuditEventConverter auditEventConverter; + + private CustomAuditEventRepository customAuditEventRepository; + + private PersistentAuditEvent testUserEvent; + + private PersistentAuditEvent testOtherUserEvent; + + private PersistentAuditEvent testOldUserEvent; + + @Before + public void setup() { + customAuditEventRepository = new CustomAuditEventRepository(persistenceAuditEventRepository, auditEventConverter); + persistenceAuditEventRepository.deleteAll(); + Instant oneHourAgo = Instant.now().minusSeconds(3600); + + testUserEvent = new PersistentAuditEvent(); + testUserEvent.setPrincipal("test-user"); + testUserEvent.setAuditEventType("test-type"); + testUserEvent.setAuditEventDate(oneHourAgo); + Map data = new HashMap<>(); + data.put("test-key", "test-value"); + testUserEvent.setData(data); + + testOldUserEvent = new PersistentAuditEvent(); + testOldUserEvent.setPrincipal("test-user"); + testOldUserEvent.setAuditEventType("test-type"); + testOldUserEvent.setAuditEventDate(oneHourAgo.minusSeconds(10000)); + + testOtherUserEvent = new PersistentAuditEvent(); + testOtherUserEvent.setPrincipal("other-test-user"); + testOtherUserEvent.setAuditEventType("test-type"); + testOtherUserEvent.setAuditEventDate(oneHourAgo); + } + + @Test + public void addAuditEvent() { + Map data = new HashMap<>(); + data.put("test-key", "test-value"); + AuditEvent event = new AuditEvent("test-user", "test-type", data); + customAuditEventRepository.add(event); + List persistentAuditEvents = persistenceAuditEventRepository.findAll(); + assertThat(persistentAuditEvents).hasSize(1); + PersistentAuditEvent persistentAuditEvent = persistentAuditEvents.get(0); + assertThat(persistentAuditEvent.getPrincipal()).isEqualTo(event.getPrincipal()); + assertThat(persistentAuditEvent.getAuditEventType()).isEqualTo(event.getType()); + assertThat(persistentAuditEvent.getData()).containsKey("test-key"); + assertThat(persistentAuditEvent.getData().get("test-key")).isEqualTo("test-value"); + assertThat(persistentAuditEvent.getAuditEventDate()).isEqualTo(event.getTimestamp()); + } + + @Test + public void addAuditEventTruncateLargeData() { + Map data = new HashMap<>(); + StringBuilder largeData = new StringBuilder(); + for (int i = 0; i < EVENT_DATA_COLUMN_MAX_LENGTH + 10; i++) { + largeData.append("a"); + } + data.put("test-key", largeData); + AuditEvent event = new AuditEvent("test-user", "test-type", data); + customAuditEventRepository.add(event); + List persistentAuditEvents = persistenceAuditEventRepository.findAll(); + assertThat(persistentAuditEvents).hasSize(1); + PersistentAuditEvent persistentAuditEvent = persistentAuditEvents.get(0); + assertThat(persistentAuditEvent.getPrincipal()).isEqualTo(event.getPrincipal()); + assertThat(persistentAuditEvent.getAuditEventType()).isEqualTo(event.getType()); + assertThat(persistentAuditEvent.getData()).containsKey("test-key"); + String actualData = persistentAuditEvent.getData().get("test-key"); + assertThat(actualData.length()).isEqualTo(EVENT_DATA_COLUMN_MAX_LENGTH); + assertThat(actualData).isSubstringOf(largeData); + assertThat(persistentAuditEvent.getAuditEventDate()).isEqualTo(event.getTimestamp()); + } + + @Test + public void testAddEventWithWebAuthenticationDetails() { + HttpSession session = new MockHttpSession(null, "test-session-id"); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setSession(session); + request.setRemoteAddr("1.2.3.4"); + WebAuthenticationDetails details = new WebAuthenticationDetails(request); + Map data = new HashMap<>(); + data.put("test-key", details); + AuditEvent event = new AuditEvent("test-user", "test-type", data); + customAuditEventRepository.add(event); + List persistentAuditEvents = persistenceAuditEventRepository.findAll(); + assertThat(persistentAuditEvents).hasSize(1); + PersistentAuditEvent persistentAuditEvent = persistentAuditEvents.get(0); + assertThat(persistentAuditEvent.getData().get("remoteAddress")).isEqualTo("1.2.3.4"); + assertThat(persistentAuditEvent.getData().get("sessionId")).isEqualTo("test-session-id"); + } + + @Test + public void testAddEventWithNullData() { + Map data = new HashMap<>(); + data.put("test-key", null); + AuditEvent event = new AuditEvent("test-user", "test-type", data); + customAuditEventRepository.add(event); + List persistentAuditEvents = persistenceAuditEventRepository.findAll(); + assertThat(persistentAuditEvents).hasSize(1); + PersistentAuditEvent persistentAuditEvent = persistentAuditEvents.get(0); + assertThat(persistentAuditEvent.getData().get("test-key")).isEqualTo("null"); + } + + @Test + public void addAuditEventWithAnonymousUser() { + Map data = new HashMap<>(); + data.put("test-key", "test-value"); + AuditEvent event = new AuditEvent(Constants.ANONYMOUS_USER, "test-type", data); + customAuditEventRepository.add(event); + List persistentAuditEvents = persistenceAuditEventRepository.findAll(); + assertThat(persistentAuditEvents).hasSize(0); + } + + @Test + public void addAuditEventWithAuthorizationFailureType() { + Map data = new HashMap<>(); + data.put("test-key", "test-value"); + AuditEvent event = new AuditEvent("test-user", "AUTHORIZATION_FAILURE", data); + customAuditEventRepository.add(event); + List persistentAuditEvents = persistenceAuditEventRepository.findAll(); + assertThat(persistentAuditEvents).hasSize(0); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/timezone/DateTimeWrapper.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/timezone/DateTimeWrapper.java new file mode 100644 index 0000000000..473a8e782e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/timezone/DateTimeWrapper.java @@ -0,0 +1,131 @@ +package com.baeldung.jhipster5.repository.timezone; + +import javax.persistence.*; +import java.io.Serializable; +import java.time.*; +import java.util.Objects; + +@Entity +@Table(name = "jhi_date_time_wrapper") +public class DateTimeWrapper implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "instant") + private Instant instant; + + @Column(name = "local_date_time") + private LocalDateTime localDateTime; + + @Column(name = "offset_date_time") + private OffsetDateTime offsetDateTime; + + @Column(name = "zoned_date_time") + private ZonedDateTime zonedDateTime; + + @Column(name = "local_time") + private LocalTime localTime; + + @Column(name = "offset_time") + private OffsetTime offsetTime; + + @Column(name = "local_date") + private LocalDate localDate; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Instant getInstant() { + return instant; + } + + public void setInstant(Instant instant) { + this.instant = instant; + } + + public LocalDateTime getLocalDateTime() { + return localDateTime; + } + + public void setLocalDateTime(LocalDateTime localDateTime) { + this.localDateTime = localDateTime; + } + + public OffsetDateTime getOffsetDateTime() { + return offsetDateTime; + } + + public void setOffsetDateTime(OffsetDateTime offsetDateTime) { + this.offsetDateTime = offsetDateTime; + } + + public ZonedDateTime getZonedDateTime() { + return zonedDateTime; + } + + public void setZonedDateTime(ZonedDateTime zonedDateTime) { + this.zonedDateTime = zonedDateTime; + } + + public LocalTime getLocalTime() { + return localTime; + } + + public void setLocalTime(LocalTime localTime) { + this.localTime = localTime; + } + + public OffsetTime getOffsetTime() { + return offsetTime; + } + + public void setOffsetTime(OffsetTime offsetTime) { + this.offsetTime = offsetTime; + } + + public LocalDate getLocalDate() { + return localDate; + } + + public void setLocalDate(LocalDate localDate) { + this.localDate = localDate; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DateTimeWrapper dateTimeWrapper = (DateTimeWrapper) o; + return !(dateTimeWrapper.getId() == null || getId() == null) && Objects.equals(getId(), dateTimeWrapper.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(getId()); + } + + @Override + public String toString() { + return "TimeZoneTest{" + + "id=" + id + + ", instant=" + instant + + ", localDateTime=" + localDateTime + + ", offsetDateTime=" + offsetDateTime + + ", zonedDateTime=" + zonedDateTime + + '}'; + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/timezone/DateTimeWrapperRepository.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/timezone/DateTimeWrapperRepository.java new file mode 100644 index 0000000000..9c3831879f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/repository/timezone/DateTimeWrapperRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.jhipster5.repository.timezone; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +/** + * Spring Data JPA repository for the DateTimeWrapper entity. + */ +@Repository +public interface DateTimeWrapperRepository extends JpaRepository { + +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/DomainUserDetailsServiceIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/DomainUserDetailsServiceIntTest.java new file mode 100644 index 0000000000..f11252de2b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/DomainUserDetailsServiceIntTest.java @@ -0,0 +1,127 @@ +package com.baeldung.jhipster5.security; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.repository.UserRepository; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test class for DomainUserDetailsService. + * + * @see DomainUserDetailsService + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +@Transactional +public class DomainUserDetailsServiceIntTest { + + private static final String USER_ONE_LOGIN = "test-user-one"; + private static final String USER_ONE_EMAIL = "test-user-one@localhost"; + private static final String USER_TWO_LOGIN = "test-user-two"; + private static final String USER_TWO_EMAIL = "test-user-two@localhost"; + private static final String USER_THREE_LOGIN = "test-user-three"; + private static final String USER_THREE_EMAIL = "test-user-three@localhost"; + + @Autowired + private UserRepository userRepository; + + @Autowired + private UserDetailsService domainUserDetailsService; + + private User userOne; + private User userTwo; + private User userThree; + + @Before + public void init() { + userOne = new User(); + userOne.setLogin(USER_ONE_LOGIN); + userOne.setPassword(RandomStringUtils.random(60)); + userOne.setActivated(true); + userOne.setEmail(USER_ONE_EMAIL); + userOne.setFirstName("userOne"); + userOne.setLastName("doe"); + userOne.setLangKey("en"); + userRepository.save(userOne); + + userTwo = new User(); + userTwo.setLogin(USER_TWO_LOGIN); + userTwo.setPassword(RandomStringUtils.random(60)); + userTwo.setActivated(true); + userTwo.setEmail(USER_TWO_EMAIL); + userTwo.setFirstName("userTwo"); + userTwo.setLastName("doe"); + userTwo.setLangKey("en"); + userRepository.save(userTwo); + + userThree = new User(); + userThree.setLogin(USER_THREE_LOGIN); + userThree.setPassword(RandomStringUtils.random(60)); + userThree.setActivated(false); + userThree.setEmail(USER_THREE_EMAIL); + userThree.setFirstName("userThree"); + userThree.setLastName("doe"); + userThree.setLangKey("en"); + userRepository.save(userThree); + } + + @Test + @Transactional + public void assertThatUserCanBeFoundByLogin() { + UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_ONE_LOGIN); + assertThat(userDetails).isNotNull(); + assertThat(userDetails.getUsername()).isEqualTo(USER_ONE_LOGIN); + } + + @Test + @Transactional + public void assertThatUserCanBeFoundByLoginIgnoreCase() { + UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_ONE_LOGIN.toUpperCase(Locale.ENGLISH)); + assertThat(userDetails).isNotNull(); + assertThat(userDetails.getUsername()).isEqualTo(USER_ONE_LOGIN); + } + + @Test + @Transactional + public void assertThatUserCanBeFoundByEmail() { + UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_TWO_EMAIL); + assertThat(userDetails).isNotNull(); + assertThat(userDetails.getUsername()).isEqualTo(USER_TWO_LOGIN); + } + + @Test(expected = UsernameNotFoundException.class) + @Transactional + public void assertThatUserCanNotBeFoundByEmailIgnoreCase() { + domainUserDetailsService.loadUserByUsername(USER_TWO_EMAIL.toUpperCase(Locale.ENGLISH)); + } + + @Test + @Transactional + public void assertThatEmailIsPrioritizedOverLogin() { + UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_ONE_EMAIL); + assertThat(userDetails).isNotNull(); + assertThat(userDetails.getUsername()).isEqualTo(USER_ONE_LOGIN); + } + + @Test(expected = UserNotActivatedException.class) + @Transactional + public void assertThatUserNotActivatedExceptionIsThrownForNotActivatedUsers() { + domainUserDetailsService.loadUserByUsername(USER_THREE_LOGIN); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/SecurityUtilsUnitTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/SecurityUtilsUnitTest.java new file mode 100644 index 0000000000..b2736badd6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/SecurityUtilsUnitTest.java @@ -0,0 +1,73 @@ +package com.baeldung.jhipster5.security; + +import org.junit.Test; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test class for the SecurityUtils utility class. + * + * @see SecurityUtils + */ +public class SecurityUtilsUnitTest { + + @Test + public void testgetCurrentUserLogin() { + SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); + securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "admin")); + SecurityContextHolder.setContext(securityContext); + Optional login = SecurityUtils.getCurrentUserLogin(); + assertThat(login).contains("admin"); + } + + @Test + public void testgetCurrentUserJWT() { + SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); + securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "token")); + SecurityContextHolder.setContext(securityContext); + Optional jwt = SecurityUtils.getCurrentUserJWT(); + assertThat(jwt).contains("token"); + } + + @Test + public void testIsAuthenticated() { + SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); + securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "admin")); + SecurityContextHolder.setContext(securityContext); + boolean isAuthenticated = SecurityUtils.isAuthenticated(); + assertThat(isAuthenticated).isTrue(); + } + + @Test + public void testAnonymousIsNotAuthenticated() { + SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); + Collection authorities = new ArrayList<>(); + authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS)); + securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities)); + SecurityContextHolder.setContext(securityContext); + boolean isAuthenticated = SecurityUtils.isAuthenticated(); + assertThat(isAuthenticated).isFalse(); + } + + @Test + public void testIsCurrentUserInRole() { + SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); + Collection authorities = new ArrayList<>(); + authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.USER)); + securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("user", "user", authorities)); + SecurityContextHolder.setContext(securityContext); + + assertThat(SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.USER)).isTrue(); + assertThat(SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)).isFalse(); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/jwt/JWTFilterTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/jwt/JWTFilterTest.java new file mode 100644 index 0000000000..b3de21819b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/jwt/JWTFilterTest.java @@ -0,0 +1,115 @@ +package com.baeldung.jhipster5.security.jwt; + +import com.baeldung.jhipster5.security.AuthoritiesConstants; +import io.github.jhipster.config.JHipsterProperties; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.security.Keys; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.MockFilterChain; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JWTFilterTest { + + private TokenProvider tokenProvider; + + private JWTFilter jwtFilter; + + @Before + public void setup() { + JHipsterProperties jHipsterProperties = new JHipsterProperties(); + tokenProvider = new TokenProvider(jHipsterProperties); + ReflectionTestUtils.setField(tokenProvider, "key", + Keys.hmacShaKeyFor(Decoders.BASE64 + .decode("fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8"))); + + ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", 60000); + jwtFilter = new JWTFilter(tokenProvider); + SecurityContextHolder.getContext().setAuthentication(null); + } + + @Test + public void testJWTFilter() throws Exception { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + "test-user", + "test-password", + Collections.singletonList(new SimpleGrantedAuthority(AuthoritiesConstants.USER)) + ); + String jwt = tokenProvider.createToken(authentication, false); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt); + request.setRequestURI("/api/test"); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain filterChain = new MockFilterChain(); + jwtFilter.doFilter(request, response, filterChain); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); + assertThat(SecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("test-user"); + assertThat(SecurityContextHolder.getContext().getAuthentication().getCredentials().toString()).isEqualTo(jwt); + } + + @Test + public void testJWTFilterInvalidToken() throws Exception { + String jwt = "wrong_jwt"; + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt); + request.setRequestURI("/api/test"); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain filterChain = new MockFilterChain(); + jwtFilter.doFilter(request, response, filterChain); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); + } + + @Test + public void testJWTFilterMissingAuthorization() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setRequestURI("/api/test"); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain filterChain = new MockFilterChain(); + jwtFilter.doFilter(request, response, filterChain); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); + } + + @Test + public void testJWTFilterMissingToken() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader(JWTFilter.AUTHORIZATION_HEADER, "Bearer "); + request.setRequestURI("/api/test"); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain filterChain = new MockFilterChain(); + jwtFilter.doFilter(request, response, filterChain); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); + } + + @Test + public void testJWTFilterWrongScheme() throws Exception { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( + "test-user", + "test-password", + Collections.singletonList(new SimpleGrantedAuthority(AuthoritiesConstants.USER)) + ); + String jwt = tokenProvider.createToken(authentication, false); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader(JWTFilter.AUTHORIZATION_HEADER, "Basic " + jwt); + request.setRequestURI("/api/test"); + MockHttpServletResponse response = new MockHttpServletResponse(); + MockFilterChain filterChain = new MockFilterChain(); + jwtFilter.doFilter(request, response, filterChain); + assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); + assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/jwt/TokenProviderTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/jwt/TokenProviderTest.java new file mode 100644 index 0000000000..11fcfddbf9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/security/jwt/TokenProviderTest.java @@ -0,0 +1,111 @@ +package com.baeldung.jhipster5.security.jwt; + +import com.baeldung.jhipster5.security.AuthoritiesConstants; + +import java.security.Key; +import java.util.*; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.test.util.ReflectionTestUtils; + +import io.github.jhipster.config.JHipsterProperties; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.io.Decoders; +import io.jsonwebtoken.security.Keys; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TokenProviderTest { + + private final long ONE_MINUTE = 60000; + private Key key; + private JHipsterProperties jHipsterProperties; + private TokenProvider tokenProvider; + + @Before + public void setup() { + jHipsterProperties = Mockito.mock(JHipsterProperties.class); + tokenProvider = new TokenProvider(jHipsterProperties); + key = Keys.hmacShaKeyFor(Decoders.BASE64 + .decode("fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8")); + + ReflectionTestUtils.setField(tokenProvider, "key", key); + ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", ONE_MINUTE); + } + + @Test + public void testReturnFalseWhenJWThasInvalidSignature() { + boolean isTokenValid = tokenProvider.validateToken(createTokenWithDifferentSignature()); + + assertThat(isTokenValid).isEqualTo(false); + } + + @Test + public void testReturnFalseWhenJWTisMalformed() { + Authentication authentication = createAuthentication(); + String token = tokenProvider.createToken(authentication, false); + String invalidToken = token.substring(1); + boolean isTokenValid = tokenProvider.validateToken(invalidToken); + + assertThat(isTokenValid).isEqualTo(false); + } + + @Test + public void testReturnFalseWhenJWTisExpired() { + ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", -ONE_MINUTE); + + Authentication authentication = createAuthentication(); + String token = tokenProvider.createToken(authentication, false); + + boolean isTokenValid = tokenProvider.validateToken(token); + + assertThat(isTokenValid).isEqualTo(false); + } + + @Test + public void testReturnFalseWhenJWTisUnsupported() { + String unsupportedToken = createUnsupportedToken(); + + boolean isTokenValid = tokenProvider.validateToken(unsupportedToken); + + assertThat(isTokenValid).isEqualTo(false); + } + + @Test + public void testReturnFalseWhenJWTisInvalid() { + boolean isTokenValid = tokenProvider.validateToken(""); + + assertThat(isTokenValid).isEqualTo(false); + } + + private Authentication createAuthentication() { + Collection authorities = new ArrayList<>(); + authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS)); + return new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities); + } + + private String createUnsupportedToken() { + return Jwts.builder() + .setPayload("payload") + .signWith(key, SignatureAlgorithm.HS512) + .compact(); + } + + private String createTokenWithDifferentSignature() { + Key otherKey = Keys.hmacShaKeyFor(Decoders.BASE64 + .decode("Xfd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8")); + + return Jwts.builder() + .setSubject("anonymous") + .signWith(otherKey, SignatureAlgorithm.HS512) + .setExpiration(new Date(new Date().getTime() + ONE_MINUTE)) + .compact(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/MailServiceIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/MailServiceIntTest.java new file mode 100644 index 0000000000..4bde3276f5 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/MailServiceIntTest.java @@ -0,0 +1,187 @@ +package com.baeldung.jhipster5.service; +import com.baeldung.jhipster5.config.Constants; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.domain.User; +import io.github.jhipster.config.JHipsterProperties; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.MessageSource; +import org.springframework.mail.MailSendException; +import org.springframework.mail.javamail.JavaMailSenderImpl; +import org.springframework.test.context.junit4.SpringRunner; +import org.thymeleaf.spring5.SpringTemplateEngine; + +import javax.mail.Multipart; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import java.io.ByteArrayOutputStream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +public class MailServiceIntTest { + + @Autowired + private JHipsterProperties jHipsterProperties; + + @Autowired + private MessageSource messageSource; + + @Autowired + private SpringTemplateEngine templateEngine; + + @Spy + private JavaMailSenderImpl javaMailSender; + + @Captor + private ArgumentCaptor messageCaptor; + + private MailService mailService; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + doNothing().when(javaMailSender).send(any(MimeMessage.class)); + mailService = new MailService(jHipsterProperties, javaMailSender, messageSource, templateEngine); + } + + @Test + public void testSendEmail() throws Exception { + mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", false, false); + verify(javaMailSender).send(messageCaptor.capture()); + MimeMessage message = messageCaptor.getValue(); + assertThat(message.getSubject()).isEqualTo("testSubject"); + assertThat(message.getAllRecipients()[0].toString()).isEqualTo("john.doe@example.com"); + assertThat(message.getFrom()[0].toString()).isEqualTo("test@localhost"); + assertThat(message.getContent()).isInstanceOf(String.class); + assertThat(message.getContent().toString()).isEqualTo("testContent"); + assertThat(message.getDataHandler().getContentType()).isEqualTo("text/plain; charset=UTF-8"); + } + + @Test + public void testSendHtmlEmail() throws Exception { + mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", false, true); + verify(javaMailSender).send(messageCaptor.capture()); + MimeMessage message = messageCaptor.getValue(); + assertThat(message.getSubject()).isEqualTo("testSubject"); + assertThat(message.getAllRecipients()[0].toString()).isEqualTo("john.doe@example.com"); + assertThat(message.getFrom()[0].toString()).isEqualTo("test@localhost"); + assertThat(message.getContent()).isInstanceOf(String.class); + assertThat(message.getContent().toString()).isEqualTo("testContent"); + assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); + } + + @Test + public void testSendMultipartEmail() throws Exception { + mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", true, false); + verify(javaMailSender).send(messageCaptor.capture()); + MimeMessage message = messageCaptor.getValue(); + MimeMultipart mp = (MimeMultipart) message.getContent(); + MimeBodyPart part = (MimeBodyPart) ((MimeMultipart) mp.getBodyPart(0).getContent()).getBodyPart(0); + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + part.writeTo(aos); + assertThat(message.getSubject()).isEqualTo("testSubject"); + assertThat(message.getAllRecipients()[0].toString()).isEqualTo("john.doe@example.com"); + assertThat(message.getFrom()[0].toString()).isEqualTo("test@localhost"); + assertThat(message.getContent()).isInstanceOf(Multipart.class); + assertThat(aos.toString()).isEqualTo("\r\ntestContent"); + assertThat(part.getDataHandler().getContentType()).isEqualTo("text/plain; charset=UTF-8"); + } + + @Test + public void testSendMultipartHtmlEmail() throws Exception { + mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", true, true); + verify(javaMailSender).send(messageCaptor.capture()); + MimeMessage message = messageCaptor.getValue(); + MimeMultipart mp = (MimeMultipart) message.getContent(); + MimeBodyPart part = (MimeBodyPart) ((MimeMultipart) mp.getBodyPart(0).getContent()).getBodyPart(0); + ByteArrayOutputStream aos = new ByteArrayOutputStream(); + part.writeTo(aos); + assertThat(message.getSubject()).isEqualTo("testSubject"); + assertThat(message.getAllRecipients()[0].toString()).isEqualTo("john.doe@example.com"); + assertThat(message.getFrom()[0].toString()).isEqualTo("test@localhost"); + assertThat(message.getContent()).isInstanceOf(Multipart.class); + assertThat(aos.toString()).isEqualTo("\r\ntestContent"); + assertThat(part.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); + } + + @Test + public void testSendEmailFromTemplate() throws Exception { + User user = new User(); + user.setLogin("john"); + user.setEmail("john.doe@example.com"); + user.setLangKey("en"); + mailService.sendEmailFromTemplate(user, "mail/testEmail", "email.test.title"); + verify(javaMailSender).send(messageCaptor.capture()); + MimeMessage message = messageCaptor.getValue(); + assertThat(message.getSubject()).isEqualTo("test title"); + assertThat(message.getAllRecipients()[0].toString()).isEqualTo(user.getEmail()); + assertThat(message.getFrom()[0].toString()).isEqualTo("test@localhost"); + assertThat(message.getContent().toString()).isEqualToNormalizingNewlines("test title, http://127.0.0.1:8080, john\n"); + assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); + } + + @Test + public void testSendActivationEmail() throws Exception { + User user = new User(); + user.setLangKey(Constants.DEFAULT_LANGUAGE); + user.setLogin("john"); + user.setEmail("john.doe@example.com"); + mailService.sendActivationEmail(user); + verify(javaMailSender).send(messageCaptor.capture()); + MimeMessage message = messageCaptor.getValue(); + assertThat(message.getAllRecipients()[0].toString()).isEqualTo(user.getEmail()); + assertThat(message.getFrom()[0].toString()).isEqualTo("test@localhost"); + assertThat(message.getContent().toString()).isNotEmpty(); + assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); + } + + @Test + public void testCreationEmail() throws Exception { + User user = new User(); + user.setLangKey(Constants.DEFAULT_LANGUAGE); + user.setLogin("john"); + user.setEmail("john.doe@example.com"); + mailService.sendCreationEmail(user); + verify(javaMailSender).send(messageCaptor.capture()); + MimeMessage message = messageCaptor.getValue(); + assertThat(message.getAllRecipients()[0].toString()).isEqualTo(user.getEmail()); + assertThat(message.getFrom()[0].toString()).isEqualTo("test@localhost"); + assertThat(message.getContent().toString()).isNotEmpty(); + assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); + } + + @Test + public void testSendPasswordResetMail() throws Exception { + User user = new User(); + user.setLangKey(Constants.DEFAULT_LANGUAGE); + user.setLogin("john"); + user.setEmail("john.doe@example.com"); + mailService.sendPasswordResetMail(user); + verify(javaMailSender).send(messageCaptor.capture()); + MimeMessage message = messageCaptor.getValue(); + assertThat(message.getAllRecipients()[0].toString()).isEqualTo(user.getEmail()); + assertThat(message.getFrom()[0].toString()).isEqualTo("test@localhost"); + assertThat(message.getContent().toString()).isNotEmpty(); + assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); + } + + @Test + public void testSendEmailWithException() throws Exception { + doThrow(MailSendException.class).when(javaMailSender).send(any(MimeMessage.class)); + mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", false, false); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/UserServiceIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/UserServiceIntTest.java new file mode 100644 index 0000000000..81034c2793 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/UserServiceIntTest.java @@ -0,0 +1,192 @@ +package com.baeldung.jhipster5.service; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.config.Constants; +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.repository.UserRepository; +import com.baeldung.jhipster5.service.dto.UserDTO; +import com.baeldung.jhipster5.service.util.RandomUtil; + +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.auditing.AuditingHandler; +import org.springframework.data.auditing.DateTimeProvider; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +/** + * Test class for the UserResource REST controller. + * + * @see UserService + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +@Transactional +public class UserServiceIntTest { + + @Autowired + private UserRepository userRepository; + + @Autowired + private UserService userService; + + @Autowired + private AuditingHandler auditingHandler; + + @Mock + DateTimeProvider dateTimeProvider; + + private User user; + + @Before + public void init() { + user = new User(); + user.setLogin("johndoe"); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(true); + user.setEmail("johndoe@localhost"); + user.setFirstName("john"); + user.setLastName("doe"); + user.setImageUrl("http://placehold.it/50x50"); + user.setLangKey("en"); + + when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.now())); + auditingHandler.setDateTimeProvider(dateTimeProvider); + } + + @Test + @Transactional + public void assertThatUserMustExistToResetPassword() { + userRepository.saveAndFlush(user); + Optional maybeUser = userService.requestPasswordReset("invalid.login@localhost"); + assertThat(maybeUser).isNotPresent(); + + maybeUser = userService.requestPasswordReset(user.getEmail()); + assertThat(maybeUser).isPresent(); + assertThat(maybeUser.orElse(null).getEmail()).isEqualTo(user.getEmail()); + assertThat(maybeUser.orElse(null).getResetDate()).isNotNull(); + assertThat(maybeUser.orElse(null).getResetKey()).isNotNull(); + } + + @Test + @Transactional + public void assertThatOnlyActivatedUserCanRequestPasswordReset() { + user.setActivated(false); + userRepository.saveAndFlush(user); + + Optional maybeUser = userService.requestPasswordReset(user.getLogin()); + assertThat(maybeUser).isNotPresent(); + userRepository.delete(user); + } + + @Test + @Transactional + public void assertThatResetKeyMustNotBeOlderThan24Hours() { + Instant daysAgo = Instant.now().minus(25, ChronoUnit.HOURS); + String resetKey = RandomUtil.generateResetKey(); + user.setActivated(true); + user.setResetDate(daysAgo); + user.setResetKey(resetKey); + userRepository.saveAndFlush(user); + + Optional maybeUser = userService.completePasswordReset("johndoe2", user.getResetKey()); + assertThat(maybeUser).isNotPresent(); + userRepository.delete(user); + } + + @Test + @Transactional + public void assertThatResetKeyMustBeValid() { + Instant daysAgo = Instant.now().minus(25, ChronoUnit.HOURS); + user.setActivated(true); + user.setResetDate(daysAgo); + user.setResetKey("1234"); + userRepository.saveAndFlush(user); + + Optional maybeUser = userService.completePasswordReset("johndoe2", user.getResetKey()); + assertThat(maybeUser).isNotPresent(); + userRepository.delete(user); + } + + @Test + @Transactional + public void assertThatUserCanResetPassword() { + String oldPassword = user.getPassword(); + Instant daysAgo = Instant.now().minus(2, ChronoUnit.HOURS); + String resetKey = RandomUtil.generateResetKey(); + user.setActivated(true); + user.setResetDate(daysAgo); + user.setResetKey(resetKey); + userRepository.saveAndFlush(user); + + Optional maybeUser = userService.completePasswordReset("johndoe2", user.getResetKey()); + assertThat(maybeUser).isPresent(); + assertThat(maybeUser.orElse(null).getResetDate()).isNull(); + assertThat(maybeUser.orElse(null).getResetKey()).isNull(); + assertThat(maybeUser.orElse(null).getPassword()).isNotEqualTo(oldPassword); + + userRepository.delete(user); + } + + @Test + @Transactional + public void testFindNotActivatedUsersByCreationDateBefore() { + Instant now = Instant.now(); + when(dateTimeProvider.getNow()).thenReturn(Optional.of(now.minus(4, ChronoUnit.DAYS))); + user.setActivated(false); + User dbUser = userRepository.saveAndFlush(user); + dbUser.setCreatedDate(now.minus(4, ChronoUnit.DAYS)); + userRepository.saveAndFlush(user); + List users = userRepository.findAllByActivatedIsFalseAndCreatedDateBefore(now.minus(3, ChronoUnit.DAYS)); + assertThat(users).isNotEmpty(); + userService.removeNotActivatedUsers(); + users = userRepository.findAllByActivatedIsFalseAndCreatedDateBefore(now.minus(3, ChronoUnit.DAYS)); + assertThat(users).isEmpty(); + } + + @Test + @Transactional + public void assertThatAnonymousUserIsNotGet() { + user.setLogin(Constants.ANONYMOUS_USER); + if (!userRepository.findOneByLogin(Constants.ANONYMOUS_USER).isPresent()) { + userRepository.saveAndFlush(user); + } + final PageRequest pageable = PageRequest.of(0, (int) userRepository.count()); + final Page allManagedUsers = userService.getAllManagedUsers(pageable); + assertThat(allManagedUsers.getContent().stream() + .noneMatch(user -> Constants.ANONYMOUS_USER.equals(user.getLogin()))) + .isTrue(); + } + + + @Test + @Transactional + public void testRemoveNotActivatedUsers() { + // custom "now" for audit to use as creation date + when(dateTimeProvider.getNow()).thenReturn(Optional.of(Instant.now().minus(30, ChronoUnit.DAYS))); + + user.setActivated(false); + userRepository.saveAndFlush(user); + + assertThat(userRepository.findOneByLogin("johndoe")).isPresent(); + userService.removeNotActivatedUsers(); + assertThat(userRepository.findOneByLogin("johndoe")).isNotPresent(); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperTest.java new file mode 100644 index 0000000000..3d66fa5813 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/service/mapper/UserMapperTest.java @@ -0,0 +1,150 @@ +package com.baeldung.jhipster5.service.mapper; + + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.service.dto.UserDTO; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test class for the UserMapper. + * + * @see UserMapper + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +public class UserMapperTest { + + private static final String DEFAULT_LOGIN = "johndoe"; + + @Autowired + private UserMapper userMapper; + + private User user; + private UserDTO userDto; + + private static final Long DEFAULT_ID = 1L; + + @Before + public void init() { + user = new User(); + user.setLogin(DEFAULT_LOGIN); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(true); + user.setEmail("johndoe@localhost"); + user.setFirstName("john"); + user.setLastName("doe"); + user.setImageUrl("image_url"); + user.setLangKey("en"); + + userDto = new UserDTO(user); + } + + @Test + public void usersToUserDTOsShouldMapOnlyNonNullUsers(){ + List users = new ArrayList<>(); + users.add(user); + users.add(null); + + List userDTOS = userMapper.usersToUserDTOs(users); + + assertThat(userDTOS).isNotEmpty(); + assertThat(userDTOS).size().isEqualTo(1); + } + + @Test + public void userDTOsToUsersShouldMapOnlyNonNullUsers(){ + List usersDto = new ArrayList<>(); + usersDto.add(userDto); + usersDto.add(null); + + List users = userMapper.userDTOsToUsers(usersDto); + + assertThat(users).isNotEmpty(); + assertThat(users).size().isEqualTo(1); + } + + @Test + public void userDTOsToUsersWithAuthoritiesStringShouldMapToUsersWithAuthoritiesDomain(){ + Set authoritiesAsString = new HashSet<>(); + authoritiesAsString.add("ADMIN"); + userDto.setAuthorities(authoritiesAsString); + + List usersDto = new ArrayList<>(); + usersDto.add(userDto); + + List users = userMapper.userDTOsToUsers(usersDto); + + assertThat(users).isNotEmpty(); + assertThat(users).size().isEqualTo(1); + assertThat(users.get(0).getAuthorities()).isNotNull(); + assertThat(users.get(0).getAuthorities()).isNotEmpty(); + assertThat(users.get(0).getAuthorities().iterator().next().getName()).isEqualTo("ADMIN"); + } + + @Test + public void userDTOsToUsersMapWithNullAuthoritiesStringShouldReturnUserWithEmptyAuthorities(){ + userDto.setAuthorities(null); + + List usersDto = new ArrayList<>(); + usersDto.add(userDto); + + List users = userMapper.userDTOsToUsers(usersDto); + + assertThat(users).isNotEmpty(); + assertThat(users).size().isEqualTo(1); + assertThat(users.get(0).getAuthorities()).isNotNull(); + assertThat(users.get(0).getAuthorities()).isEmpty(); + } + + @Test + public void userDTOToUserMapWithAuthoritiesStringShouldReturnUserWithAuthorities(){ + Set authoritiesAsString = new HashSet<>(); + authoritiesAsString.add("ADMIN"); + userDto.setAuthorities(authoritiesAsString); + + userDto.setAuthorities(authoritiesAsString); + + User user = userMapper.userDTOToUser(userDto); + + assertThat(user).isNotNull(); + assertThat(user.getAuthorities()).isNotNull(); + assertThat(user.getAuthorities()).isNotEmpty(); + assertThat(user.getAuthorities().iterator().next().getName()).isEqualTo("ADMIN"); + } + + @Test + public void userDTOToUserMapWithNullAuthoritiesStringShouldReturnUserWithEmptyAuthorities(){ + userDto.setAuthorities(null); + + User user = userMapper.userDTOToUser(userDto); + + assertThat(user).isNotNull(); + assertThat(user.getAuthorities()).isNotNull(); + assertThat(user.getAuthorities()).isEmpty(); + } + + @Test + public void userDTOToUserMapWithNullUserShouldReturnNull(){ + assertThat(userMapper.userDTOToUser(null)).isNull(); + } + + @Test + public void testUserFromId() { + assertThat(userMapper.userFromId(DEFAULT_ID).getId()).isEqualTo(DEFAULT_ID); + assertThat(userMapper.userFromId(null)).isNull(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/AccountResourceIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/AccountResourceIntTest.java new file mode 100644 index 0000000000..6db284a87f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/AccountResourceIntTest.java @@ -0,0 +1,818 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.config.Constants; +import com.baeldung.jhipster5.domain.Authority; +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.repository.AuthorityRepository; +import com.baeldung.jhipster5.repository.UserRepository; +import com.baeldung.jhipster5.security.AuthoritiesConstants; +import com.baeldung.jhipster5.service.MailService; +import com.baeldung.jhipster5.service.UserService; +import com.baeldung.jhipster5.service.dto.PasswordChangeDTO; +import com.baeldung.jhipster5.service.dto.UserDTO; +import com.baeldung.jhipster5.web.rest.errors.ExceptionTranslator; +import com.baeldung.jhipster5.web.rest.vm.KeyAndPasswordVM; +import com.baeldung.jhipster5.web.rest.vm.ManagedUserVM; +import org.apache.commons.lang3.RandomStringUtils; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Instant; +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +/** + * Test class for the AccountResource REST controller. + * + * @see AccountResource + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +public class AccountResourceIntTest { + + @Autowired + private UserRepository userRepository; + + @Autowired + private AuthorityRepository authorityRepository; + + @Autowired + private UserService userService; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private HttpMessageConverter[] httpMessageConverters; + + @Autowired + private ExceptionTranslator exceptionTranslator; + + @Mock + private UserService mockUserService; + + @Mock + private MailService mockMailService; + + private MockMvc restMvc; + + private MockMvc restUserMockMvc; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + doNothing().when(mockMailService).sendActivationEmail(any()); + AccountResource accountResource = + new AccountResource(userRepository, userService, mockMailService); + + AccountResource accountUserMockResource = + new AccountResource(userRepository, mockUserService, mockMailService); + this.restMvc = MockMvcBuilders.standaloneSetup(accountResource) + .setMessageConverters(httpMessageConverters) + .setControllerAdvice(exceptionTranslator) + .build(); + this.restUserMockMvc = MockMvcBuilders.standaloneSetup(accountUserMockResource) + .setControllerAdvice(exceptionTranslator) + .build(); + } + + @Test + public void testNonAuthenticatedUser() throws Exception { + restUserMockMvc.perform(get("/api/authenticate") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string("")); + } + + @Test + public void testAuthenticatedUser() throws Exception { + restUserMockMvc.perform(get("/api/authenticate") + .with(request -> { + request.setRemoteUser("test"); + return request; + }) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string("test")); + } + + @Test + public void testGetExistingAccount() throws Exception { + Set authorities = new HashSet<>(); + Authority authority = new Authority(); + authority.setName(AuthoritiesConstants.ADMIN); + authorities.add(authority); + + User user = new User(); + user.setLogin("test"); + user.setFirstName("john"); + user.setLastName("doe"); + user.setEmail("john.doe@jhipster.com"); + user.setImageUrl("http://placehold.it/50x50"); + user.setLangKey("en"); + user.setAuthorities(authorities); + when(mockUserService.getUserWithAuthorities()).thenReturn(Optional.of(user)); + + restUserMockMvc.perform(get("/api/account") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(jsonPath("$.login").value("test")) + .andExpect(jsonPath("$.firstName").value("john")) + .andExpect(jsonPath("$.lastName").value("doe")) + .andExpect(jsonPath("$.email").value("john.doe@jhipster.com")) + .andExpect(jsonPath("$.imageUrl").value("http://placehold.it/50x50")) + .andExpect(jsonPath("$.langKey").value("en")) + .andExpect(jsonPath("$.authorities").value(AuthoritiesConstants.ADMIN)); + } + + @Test + public void testGetUnknownAccount() throws Exception { + when(mockUserService.getUserWithAuthorities()).thenReturn(Optional.empty()); + + restUserMockMvc.perform(get("/api/account") + .accept(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(status().isInternalServerError()); + } + + @Test + @Transactional + public void testRegisterValid() throws Exception { + ManagedUserVM validUser = new ManagedUserVM(); + validUser.setLogin("test-register-valid"); + validUser.setPassword("password"); + validUser.setFirstName("Alice"); + validUser.setLastName("Test"); + validUser.setEmail("test-register-valid@example.com"); + validUser.setImageUrl("http://placehold.it/50x50"); + validUser.setLangKey(Constants.DEFAULT_LANGUAGE); + validUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + assertThat(userRepository.findOneByLogin("test-register-valid").isPresent()).isFalse(); + + restMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(validUser))) + .andExpect(status().isCreated()); + + assertThat(userRepository.findOneByLogin("test-register-valid").isPresent()).isTrue(); + } + + @Test + @Transactional + public void testRegisterInvalidLogin() throws Exception { + ManagedUserVM invalidUser = new ManagedUserVM(); + invalidUser.setLogin("funky-log!n");// <-- invalid + invalidUser.setPassword("password"); + invalidUser.setFirstName("Funky"); + invalidUser.setLastName("One"); + invalidUser.setEmail("funky@example.com"); + invalidUser.setActivated(true); + invalidUser.setImageUrl("http://placehold.it/50x50"); + invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE); + invalidUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + restUserMockMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(invalidUser))) + .andExpect(status().isBadRequest()); + + Optional user = userRepository.findOneByEmailIgnoreCase("funky@example.com"); + assertThat(user.isPresent()).isFalse(); + } + + @Test + @Transactional + public void testRegisterInvalidEmail() throws Exception { + ManagedUserVM invalidUser = new ManagedUserVM(); + invalidUser.setLogin("bob"); + invalidUser.setPassword("password"); + invalidUser.setFirstName("Bob"); + invalidUser.setLastName("Green"); + invalidUser.setEmail("invalid");// <-- invalid + invalidUser.setActivated(true); + invalidUser.setImageUrl("http://placehold.it/50x50"); + invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE); + invalidUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + restUserMockMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(invalidUser))) + .andExpect(status().isBadRequest()); + + Optional user = userRepository.findOneByLogin("bob"); + assertThat(user.isPresent()).isFalse(); + } + + @Test + @Transactional + public void testRegisterInvalidPassword() throws Exception { + ManagedUserVM invalidUser = new ManagedUserVM(); + invalidUser.setLogin("bob"); + invalidUser.setPassword("123");// password with only 3 digits + invalidUser.setFirstName("Bob"); + invalidUser.setLastName("Green"); + invalidUser.setEmail("bob@example.com"); + invalidUser.setActivated(true); + invalidUser.setImageUrl("http://placehold.it/50x50"); + invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE); + invalidUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + restUserMockMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(invalidUser))) + .andExpect(status().isBadRequest()); + + Optional user = userRepository.findOneByLogin("bob"); + assertThat(user.isPresent()).isFalse(); + } + + @Test + @Transactional + public void testRegisterNullPassword() throws Exception { + ManagedUserVM invalidUser = new ManagedUserVM(); + invalidUser.setLogin("bob"); + invalidUser.setPassword(null);// invalid null password + invalidUser.setFirstName("Bob"); + invalidUser.setLastName("Green"); + invalidUser.setEmail("bob@example.com"); + invalidUser.setActivated(true); + invalidUser.setImageUrl("http://placehold.it/50x50"); + invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE); + invalidUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + restUserMockMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(invalidUser))) + .andExpect(status().isBadRequest()); + + Optional user = userRepository.findOneByLogin("bob"); + assertThat(user.isPresent()).isFalse(); + } + + @Test + @Transactional + public void testRegisterDuplicateLogin() throws Exception { + // First registration + ManagedUserVM firstUser = new ManagedUserVM(); + firstUser.setLogin("alice"); + firstUser.setPassword("password"); + firstUser.setFirstName("Alice"); + firstUser.setLastName("Something"); + firstUser.setEmail("alice@example.com"); + firstUser.setImageUrl("http://placehold.it/50x50"); + firstUser.setLangKey(Constants.DEFAULT_LANGUAGE); + firstUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + // Duplicate login, different email + ManagedUserVM secondUser = new ManagedUserVM(); + secondUser.setLogin(firstUser.getLogin()); + secondUser.setPassword(firstUser.getPassword()); + secondUser.setFirstName(firstUser.getFirstName()); + secondUser.setLastName(firstUser.getLastName()); + secondUser.setEmail("alice2@example.com"); + secondUser.setImageUrl(firstUser.getImageUrl()); + secondUser.setLangKey(firstUser.getLangKey()); + secondUser.setCreatedBy(firstUser.getCreatedBy()); + secondUser.setCreatedDate(firstUser.getCreatedDate()); + secondUser.setLastModifiedBy(firstUser.getLastModifiedBy()); + secondUser.setLastModifiedDate(firstUser.getLastModifiedDate()); + secondUser.setAuthorities(new HashSet<>(firstUser.getAuthorities())); + + // First user + restMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(firstUser))) + .andExpect(status().isCreated()); + + // Second (non activated) user + restMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(secondUser))) + .andExpect(status().isCreated()); + + Optional testUser = userRepository.findOneByEmailIgnoreCase("alice2@example.com"); + assertThat(testUser.isPresent()).isTrue(); + testUser.get().setActivated(true); + userRepository.save(testUser.get()); + + // Second (already activated) user + restMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(secondUser))) + .andExpect(status().is4xxClientError()); + } + + @Test + @Transactional + public void testRegisterDuplicateEmail() throws Exception { + // First user + ManagedUserVM firstUser = new ManagedUserVM(); + firstUser.setLogin("test-register-duplicate-email"); + firstUser.setPassword("password"); + firstUser.setFirstName("Alice"); + firstUser.setLastName("Test"); + firstUser.setEmail("test-register-duplicate-email@example.com"); + firstUser.setImageUrl("http://placehold.it/50x50"); + firstUser.setLangKey(Constants.DEFAULT_LANGUAGE); + firstUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + // Register first user + restMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(firstUser))) + .andExpect(status().isCreated()); + + Optional testUser1 = userRepository.findOneByLogin("test-register-duplicate-email"); + assertThat(testUser1.isPresent()).isTrue(); + + // Duplicate email, different login + ManagedUserVM secondUser = new ManagedUserVM(); + secondUser.setLogin("test-register-duplicate-email-2"); + secondUser.setPassword(firstUser.getPassword()); + secondUser.setFirstName(firstUser.getFirstName()); + secondUser.setLastName(firstUser.getLastName()); + secondUser.setEmail(firstUser.getEmail()); + secondUser.setImageUrl(firstUser.getImageUrl()); + secondUser.setLangKey(firstUser.getLangKey()); + secondUser.setAuthorities(new HashSet<>(firstUser.getAuthorities())); + + // Register second (non activated) user + restMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(secondUser))) + .andExpect(status().isCreated()); + + Optional testUser2 = userRepository.findOneByLogin("test-register-duplicate-email"); + assertThat(testUser2.isPresent()).isFalse(); + + Optional testUser3 = userRepository.findOneByLogin("test-register-duplicate-email-2"); + assertThat(testUser3.isPresent()).isTrue(); + + // Duplicate email - with uppercase email address + ManagedUserVM userWithUpperCaseEmail = new ManagedUserVM(); + userWithUpperCaseEmail.setId(firstUser.getId()); + userWithUpperCaseEmail.setLogin("test-register-duplicate-email-3"); + userWithUpperCaseEmail.setPassword(firstUser.getPassword()); + userWithUpperCaseEmail.setFirstName(firstUser.getFirstName()); + userWithUpperCaseEmail.setLastName(firstUser.getLastName()); + userWithUpperCaseEmail.setEmail("TEST-register-duplicate-email@example.com"); + userWithUpperCaseEmail.setImageUrl(firstUser.getImageUrl()); + userWithUpperCaseEmail.setLangKey(firstUser.getLangKey()); + userWithUpperCaseEmail.setAuthorities(new HashSet<>(firstUser.getAuthorities())); + + // Register third (not activated) user + restMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(userWithUpperCaseEmail))) + .andExpect(status().isCreated()); + + Optional testUser4 = userRepository.findOneByLogin("test-register-duplicate-email-3"); + assertThat(testUser4.isPresent()).isTrue(); + assertThat(testUser4.get().getEmail()).isEqualTo("test-register-duplicate-email@example.com"); + + testUser4.get().setActivated(true); + userService.updateUser((new UserDTO(testUser4.get()))); + + // Register 4th (already activated) user + restMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(secondUser))) + .andExpect(status().is4xxClientError()); + } + + @Test + @Transactional + public void testRegisterAdminIsIgnored() throws Exception { + ManagedUserVM validUser = new ManagedUserVM(); + validUser.setLogin("badguy"); + validUser.setPassword("password"); + validUser.setFirstName("Bad"); + validUser.setLastName("Guy"); + validUser.setEmail("badguy@example.com"); + validUser.setActivated(true); + validUser.setImageUrl("http://placehold.it/50x50"); + validUser.setLangKey(Constants.DEFAULT_LANGUAGE); + validUser.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); + + restMvc.perform( + post("/api/register") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(validUser))) + .andExpect(status().isCreated()); + + Optional userDup = userRepository.findOneByLogin("badguy"); + assertThat(userDup.isPresent()).isTrue(); + assertThat(userDup.get().getAuthorities()).hasSize(1) + .containsExactly(authorityRepository.findById(AuthoritiesConstants.USER).get()); + } + + @Test + @Transactional + public void testActivateAccount() throws Exception { + final String activationKey = "some activation key"; + User user = new User(); + user.setLogin("activate-account"); + user.setEmail("activate-account@example.com"); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(false); + user.setActivationKey(activationKey); + + userRepository.saveAndFlush(user); + + restMvc.perform(get("/api/activate?key={activationKey}", activationKey)) + .andExpect(status().isOk()); + + user = userRepository.findOneByLogin(user.getLogin()).orElse(null); + assertThat(user.getActivated()).isTrue(); + } + + @Test + @Transactional + public void testActivateAccountWithWrongKey() throws Exception { + restMvc.perform(get("/api/activate?key=wrongActivationKey")) + .andExpect(status().isInternalServerError()); + } + + @Test + @Transactional + @WithMockUser("save-account") + public void testSaveAccount() throws Exception { + User user = new User(); + user.setLogin("save-account"); + user.setEmail("save-account@example.com"); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(true); + + userRepository.saveAndFlush(user); + + UserDTO userDTO = new UserDTO(); + userDTO.setLogin("not-used"); + userDTO.setFirstName("firstname"); + userDTO.setLastName("lastname"); + userDTO.setEmail("save-account@example.com"); + userDTO.setActivated(false); + userDTO.setImageUrl("http://placehold.it/50x50"); + userDTO.setLangKey(Constants.DEFAULT_LANGUAGE); + userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); + + restMvc.perform( + post("/api/account") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(userDTO))) + .andExpect(status().isOk()); + + User updatedUser = userRepository.findOneByLogin(user.getLogin()).orElse(null); + assertThat(updatedUser.getFirstName()).isEqualTo(userDTO.getFirstName()); + assertThat(updatedUser.getLastName()).isEqualTo(userDTO.getLastName()); + assertThat(updatedUser.getEmail()).isEqualTo(userDTO.getEmail()); + assertThat(updatedUser.getLangKey()).isEqualTo(userDTO.getLangKey()); + assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword()); + assertThat(updatedUser.getImageUrl()).isEqualTo(userDTO.getImageUrl()); + assertThat(updatedUser.getActivated()).isEqualTo(true); + assertThat(updatedUser.getAuthorities()).isEmpty(); + } + + @Test + @Transactional + @WithMockUser("save-invalid-email") + public void testSaveInvalidEmail() throws Exception { + User user = new User(); + user.setLogin("save-invalid-email"); + user.setEmail("save-invalid-email@example.com"); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(true); + + userRepository.saveAndFlush(user); + + UserDTO userDTO = new UserDTO(); + userDTO.setLogin("not-used"); + userDTO.setFirstName("firstname"); + userDTO.setLastName("lastname"); + userDTO.setEmail("invalid email"); + userDTO.setActivated(false); + userDTO.setImageUrl("http://placehold.it/50x50"); + userDTO.setLangKey(Constants.DEFAULT_LANGUAGE); + userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); + + restMvc.perform( + post("/api/account") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(userDTO))) + .andExpect(status().isBadRequest()); + + assertThat(userRepository.findOneByEmailIgnoreCase("invalid email")).isNotPresent(); + } + + @Test + @Transactional + @WithMockUser("save-existing-email") + public void testSaveExistingEmail() throws Exception { + User user = new User(); + user.setLogin("save-existing-email"); + user.setEmail("save-existing-email@example.com"); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(true); + + userRepository.saveAndFlush(user); + + User anotherUser = new User(); + anotherUser.setLogin("save-existing-email2"); + anotherUser.setEmail("save-existing-email2@example.com"); + anotherUser.setPassword(RandomStringUtils.random(60)); + anotherUser.setActivated(true); + + userRepository.saveAndFlush(anotherUser); + + UserDTO userDTO = new UserDTO(); + userDTO.setLogin("not-used"); + userDTO.setFirstName("firstname"); + userDTO.setLastName("lastname"); + userDTO.setEmail("save-existing-email2@example.com"); + userDTO.setActivated(false); + userDTO.setImageUrl("http://placehold.it/50x50"); + userDTO.setLangKey(Constants.DEFAULT_LANGUAGE); + userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); + + restMvc.perform( + post("/api/account") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(userDTO))) + .andExpect(status().isBadRequest()); + + User updatedUser = userRepository.findOneByLogin("save-existing-email").orElse(null); + assertThat(updatedUser.getEmail()).isEqualTo("save-existing-email@example.com"); + } + + @Test + @Transactional + @WithMockUser("save-existing-email-and-login") + public void testSaveExistingEmailAndLogin() throws Exception { + User user = new User(); + user.setLogin("save-existing-email-and-login"); + user.setEmail("save-existing-email-and-login@example.com"); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(true); + + userRepository.saveAndFlush(user); + + UserDTO userDTO = new UserDTO(); + userDTO.setLogin("not-used"); + userDTO.setFirstName("firstname"); + userDTO.setLastName("lastname"); + userDTO.setEmail("save-existing-email-and-login@example.com"); + userDTO.setActivated(false); + userDTO.setImageUrl("http://placehold.it/50x50"); + userDTO.setLangKey(Constants.DEFAULT_LANGUAGE); + userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); + + restMvc.perform( + post("/api/account") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(userDTO))) + .andExpect(status().isOk()); + + User updatedUser = userRepository.findOneByLogin("save-existing-email-and-login").orElse(null); + assertThat(updatedUser.getEmail()).isEqualTo("save-existing-email-and-login@example.com"); + } + + @Test + @Transactional + @WithMockUser("change-password-wrong-existing-password") + public void testChangePasswordWrongExistingPassword() throws Exception { + User user = new User(); + String currentPassword = RandomStringUtils.random(60); + user.setPassword(passwordEncoder.encode(currentPassword)); + user.setLogin("change-password-wrong-existing-password"); + user.setEmail("change-password-wrong-existing-password@example.com"); + userRepository.saveAndFlush(user); + + restMvc.perform(post("/api/account/change-password") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO("1"+currentPassword, "new password")))) + .andExpect(status().isBadRequest()); + + User updatedUser = userRepository.findOneByLogin("change-password-wrong-existing-password").orElse(null); + assertThat(passwordEncoder.matches("new password", updatedUser.getPassword())).isFalse(); + assertThat(passwordEncoder.matches(currentPassword, updatedUser.getPassword())).isTrue(); + } + + @Test + @Transactional + @WithMockUser("change-password") + public void testChangePassword() throws Exception { + User user = new User(); + String currentPassword = RandomStringUtils.random(60); + user.setPassword(passwordEncoder.encode(currentPassword)); + user.setLogin("change-password"); + user.setEmail("change-password@example.com"); + userRepository.saveAndFlush(user); + + restMvc.perform(post("/api/account/change-password") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO(currentPassword, "new password")))) + .andExpect(status().isOk()); + + User updatedUser = userRepository.findOneByLogin("change-password").orElse(null); + assertThat(passwordEncoder.matches("new password", updatedUser.getPassword())).isTrue(); + } + + @Test + @Transactional + @WithMockUser("change-password-too-small") + public void testChangePasswordTooSmall() throws Exception { + User user = new User(); + String currentPassword = RandomStringUtils.random(60); + user.setPassword(passwordEncoder.encode(currentPassword)); + user.setLogin("change-password-too-small"); + user.setEmail("change-password-too-small@example.com"); + userRepository.saveAndFlush(user); + + String newPassword = RandomStringUtils.random(ManagedUserVM.PASSWORD_MIN_LENGTH - 1); + + restMvc.perform(post("/api/account/change-password") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO(currentPassword, newPassword)))) + .andExpect(status().isBadRequest()); + + User updatedUser = userRepository.findOneByLogin("change-password-too-small").orElse(null); + assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword()); + } + + @Test + @Transactional + @WithMockUser("change-password-too-long") + public void testChangePasswordTooLong() throws Exception { + User user = new User(); + String currentPassword = RandomStringUtils.random(60); + user.setPassword(passwordEncoder.encode(currentPassword)); + user.setLogin("change-password-too-long"); + user.setEmail("change-password-too-long@example.com"); + userRepository.saveAndFlush(user); + + String newPassword = RandomStringUtils.random(ManagedUserVM.PASSWORD_MAX_LENGTH + 1); + + restMvc.perform(post("/api/account/change-password") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO(currentPassword, newPassword)))) + .andExpect(status().isBadRequest()); + + User updatedUser = userRepository.findOneByLogin("change-password-too-long").orElse(null); + assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword()); + } + + @Test + @Transactional + @WithMockUser("change-password-empty") + public void testChangePasswordEmpty() throws Exception { + User user = new User(); + String currentPassword = RandomStringUtils.random(60); + user.setPassword(passwordEncoder.encode(currentPassword)); + user.setLogin("change-password-empty"); + user.setEmail("change-password-empty@example.com"); + userRepository.saveAndFlush(user); + + restMvc.perform(post("/api/account/change-password") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO(currentPassword, "")))) + .andExpect(status().isBadRequest()); + + User updatedUser = userRepository.findOneByLogin("change-password-empty").orElse(null); + assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword()); + } + + @Test + @Transactional + public void testRequestPasswordReset() throws Exception { + User user = new User(); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(true); + user.setLogin("password-reset"); + user.setEmail("password-reset@example.com"); + userRepository.saveAndFlush(user); + + restMvc.perform(post("/api/account/reset-password/init") + .content("password-reset@example.com")) + .andExpect(status().isOk()); + } + + @Test + @Transactional + public void testRequestPasswordResetUpperCaseEmail() throws Exception { + User user = new User(); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(true); + user.setLogin("password-reset"); + user.setEmail("password-reset@example.com"); + userRepository.saveAndFlush(user); + + restMvc.perform(post("/api/account/reset-password/init") + .content("password-reset@EXAMPLE.COM")) + .andExpect(status().isOk()); + } + + @Test + public void testRequestPasswordResetWrongEmail() throws Exception { + restMvc.perform( + post("/api/account/reset-password/init") + .content("password-reset-wrong-email@example.com")) + .andExpect(status().isBadRequest()); + } + + @Test + @Transactional + public void testFinishPasswordReset() throws Exception { + User user = new User(); + user.setPassword(RandomStringUtils.random(60)); + user.setLogin("finish-password-reset"); + user.setEmail("finish-password-reset@example.com"); + user.setResetDate(Instant.now().plusSeconds(60)); + user.setResetKey("reset key"); + userRepository.saveAndFlush(user); + + KeyAndPasswordVM keyAndPassword = new KeyAndPasswordVM(); + keyAndPassword.setKey(user.getResetKey()); + keyAndPassword.setNewPassword("new password"); + + restMvc.perform( + post("/api/account/reset-password/finish") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(keyAndPassword))) + .andExpect(status().isOk()); + + User updatedUser = userRepository.findOneByLogin(user.getLogin()).orElse(null); + assertThat(passwordEncoder.matches(keyAndPassword.getNewPassword(), updatedUser.getPassword())).isTrue(); + } + + @Test + @Transactional + public void testFinishPasswordResetTooSmall() throws Exception { + User user = new User(); + user.setPassword(RandomStringUtils.random(60)); + user.setLogin("finish-password-reset-too-small"); + user.setEmail("finish-password-reset-too-small@example.com"); + user.setResetDate(Instant.now().plusSeconds(60)); + user.setResetKey("reset key too small"); + userRepository.saveAndFlush(user); + + KeyAndPasswordVM keyAndPassword = new KeyAndPasswordVM(); + keyAndPassword.setKey(user.getResetKey()); + keyAndPassword.setNewPassword("foo"); + + restMvc.perform( + post("/api/account/reset-password/finish") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(keyAndPassword))) + .andExpect(status().isBadRequest()); + + User updatedUser = userRepository.findOneByLogin(user.getLogin()).orElse(null); + assertThat(passwordEncoder.matches(keyAndPassword.getNewPassword(), updatedUser.getPassword())).isFalse(); + } + + + @Test + @Transactional + public void testFinishPasswordResetWrongKey() throws Exception { + KeyAndPasswordVM keyAndPassword = new KeyAndPasswordVM(); + keyAndPassword.setKey("wrong reset key"); + keyAndPassword.setNewPassword("new password"); + + restMvc.perform( + post("/api/account/reset-password/finish") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(keyAndPassword))) + .andExpect(status().isInternalServerError()); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/AuditResourceIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/AuditResourceIntTest.java new file mode 100644 index 0000000000..c3b91ab390 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/AuditResourceIntTest.java @@ -0,0 +1,162 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.config.audit.AuditEventConverter; +import com.baeldung.jhipster5.domain.PersistentAuditEvent; +import com.baeldung.jhipster5.repository.PersistenceAuditEventRepository; +import com.baeldung.jhipster5.service.AuditEventService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.web.PageableHandlerMethodArgumentResolver; +import org.springframework.format.support.FormattingConversionService; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; + +import java.time.Instant; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +/** + * Test class for the AuditResource REST controller. + * + * @see AuditResource + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +@Transactional +public class AuditResourceIntTest { + + private static final String SAMPLE_PRINCIPAL = "SAMPLE_PRINCIPAL"; + private static final String SAMPLE_TYPE = "SAMPLE_TYPE"; + private static final Instant SAMPLE_TIMESTAMP = Instant.parse("2015-08-04T10:11:30Z"); + private static final long SECONDS_PER_DAY = 60 * 60 * 24; + + @Autowired + private PersistenceAuditEventRepository auditEventRepository; + + @Autowired + private AuditEventConverter auditEventConverter; + + @Autowired + private MappingJackson2HttpMessageConverter jacksonMessageConverter; + + @Autowired + private FormattingConversionService formattingConversionService; + + @Autowired + private PageableHandlerMethodArgumentResolver pageableArgumentResolver; + + private PersistentAuditEvent auditEvent; + + private MockMvc restAuditMockMvc; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + AuditEventService auditEventService = + new AuditEventService(auditEventRepository, auditEventConverter); + AuditResource auditResource = new AuditResource(auditEventService); + this.restAuditMockMvc = MockMvcBuilders.standaloneSetup(auditResource) + .setCustomArgumentResolvers(pageableArgumentResolver) + .setConversionService(formattingConversionService) + .setMessageConverters(jacksonMessageConverter).build(); + } + + @Before + public void initTest() { + auditEventRepository.deleteAll(); + auditEvent = new PersistentAuditEvent(); + auditEvent.setAuditEventType(SAMPLE_TYPE); + auditEvent.setPrincipal(SAMPLE_PRINCIPAL); + auditEvent.setAuditEventDate(SAMPLE_TIMESTAMP); + } + + @Test + public void getAllAudits() throws Exception { + // Initialize the database + auditEventRepository.save(auditEvent); + + // Get all the audits + restAuditMockMvc.perform(get("/management/audits")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(jsonPath("$.[*].principal").value(hasItem(SAMPLE_PRINCIPAL))); + } + + @Test + public void getAudit() throws Exception { + // Initialize the database + auditEventRepository.save(auditEvent); + + // Get the audit + restAuditMockMvc.perform(get("/management/audits/{id}", auditEvent.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(jsonPath("$.principal").value(SAMPLE_PRINCIPAL)); + } + + @Test + public void getAuditsByDate() throws Exception { + // Initialize the database + auditEventRepository.save(auditEvent); + + // Generate dates for selecting audits by date, making sure the period will contain the audit + String fromDate = SAMPLE_TIMESTAMP.minusSeconds(SECONDS_PER_DAY).toString().substring(0, 10); + String toDate = SAMPLE_TIMESTAMP.plusSeconds(SECONDS_PER_DAY).toString().substring(0, 10); + + // Get the audit + restAuditMockMvc.perform(get("/management/audits?fromDate="+fromDate+"&toDate="+toDate)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(jsonPath("$.[*].principal").value(hasItem(SAMPLE_PRINCIPAL))); + } + + @Test + public void getNonExistingAuditsByDate() throws Exception { + // Initialize the database + auditEventRepository.save(auditEvent); + + // Generate dates for selecting audits by date, making sure the period will not contain the sample audit + String fromDate = SAMPLE_TIMESTAMP.minusSeconds(2*SECONDS_PER_DAY).toString().substring(0, 10); + String toDate = SAMPLE_TIMESTAMP.minusSeconds(SECONDS_PER_DAY).toString().substring(0, 10); + + // Query audits but expect no results + restAuditMockMvc.perform(get("/management/audits?fromDate=" + fromDate + "&toDate=" + toDate)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(header().string("X-Total-Count", "0")); + } + + @Test + public void getNonExistingAudit() throws Exception { + // Get the audit + restAuditMockMvc.perform(get("/management/audits/{id}", Long.MAX_VALUE)) + .andExpect(status().isNotFound()); + } + + @Test + @Transactional + public void testPersistentAuditEventEquals() throws Exception { + TestUtil.equalsVerifier(PersistentAuditEvent.class); + PersistentAuditEvent auditEvent1 = new PersistentAuditEvent(); + auditEvent1.setId(1L); + PersistentAuditEvent auditEvent2 = new PersistentAuditEvent(); + auditEvent2.setId(auditEvent1.getId()); + assertThat(auditEvent1).isEqualTo(auditEvent2); + auditEvent2.setId(2L); + assertThat(auditEvent1).isNotEqualTo(auditEvent2); + auditEvent1.setId(null); + assertThat(auditEvent1).isNotEqualTo(auditEvent2); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/LogsResourceIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/LogsResourceIntTest.java new file mode 100644 index 0000000000..62f7f3f17c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/LogsResourceIntTest.java @@ -0,0 +1,66 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.web.rest.vm.LoggerVM; +import ch.qos.logback.classic.AsyncAppender; +import ch.qos.logback.classic.LoggerContext; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.LoggerFactory; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * Test class for the LogsResource REST controller. + * + * @see LogsResource + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +public class LogsResourceIntTest { + + private MockMvc restLogsMockMvc; + + @Before + public void setup() { + LogsResource logsResource = new LogsResource(); + this.restLogsMockMvc = MockMvcBuilders + .standaloneSetup(logsResource) + .build(); + } + + @Test + public void getAllLogs() throws Exception { + restLogsMockMvc.perform(get("/management/logs")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)); + } + + @Test + public void changeLogs() throws Exception { + LoggerVM logger = new LoggerVM(); + logger.setLevel("INFO"); + logger.setName("ROOT"); + + restLogsMockMvc.perform(put("/management/logs") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(logger))) + .andExpect(status().isNoContent()); + } + + @Test + public void testLogstashAppender() { + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + assertThat(context.getLogger("ROOT").getAppender("ASYNC_LOGSTASH")).isInstanceOf(AsyncAppender.class); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/TestUtil.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/TestUtil.java new file mode 100644 index 0000000000..403bb9c9b0 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/TestUtil.java @@ -0,0 +1,141 @@ +package com.baeldung.jhipster5.web.rest; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.hamcrest.Description; +import org.hamcrest.TypeSafeDiagnosingMatcher; +import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar; +import org.springframework.format.support.DefaultFormattingConversionService; +import org.springframework.format.support.FormattingConversionService; +import org.springframework.http.MediaType; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.ZonedDateTime; +import java.time.format.DateTimeParseException; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Utility class for testing REST controllers. + */ +public final class TestUtil { + + private static final ObjectMapper mapper = createObjectMapper(); + + /** MediaType for JSON UTF8 */ + public static final MediaType APPLICATION_JSON_UTF8 = new MediaType( + MediaType.APPLICATION_JSON.getType(), + MediaType.APPLICATION_JSON.getSubtype(), StandardCharsets.UTF_8); + + + private static ObjectMapper createObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); + mapper.registerModule(new JavaTimeModule()); + return mapper; + } + + /** + * Convert an object to JSON byte array. + * + * @param object + * the object to convert + * @return the JSON byte array + * @throws IOException + */ + public static byte[] convertObjectToJsonBytes(Object object) + throws IOException { + return mapper.writeValueAsBytes(object); + } + + /** + * Create a byte array with a specific size filled with specified data. + * + * @param size the size of the byte array + * @param data the data to put in the byte array + * @return the JSON byte array + */ + public static byte[] createByteArray(int size, String data) { + byte[] byteArray = new byte[size]; + for (int i = 0; i < size; i++) { + byteArray[i] = Byte.parseByte(data, 2); + } + return byteArray; + } + + /** + * A matcher that tests that the examined string represents the same instant as the reference datetime. + */ + public static class ZonedDateTimeMatcher extends TypeSafeDiagnosingMatcher { + + private final ZonedDateTime date; + + public ZonedDateTimeMatcher(ZonedDateTime date) { + this.date = date; + } + + @Override + protected boolean matchesSafely(String item, Description mismatchDescription) { + try { + if (!date.isEqual(ZonedDateTime.parse(item))) { + mismatchDescription.appendText("was ").appendValue(item); + return false; + } + return true; + } catch (DateTimeParseException e) { + mismatchDescription.appendText("was ").appendValue(item) + .appendText(", which could not be parsed as a ZonedDateTime"); + return false; + } + + } + + @Override + public void describeTo(Description description) { + description.appendText("a String representing the same Instant as ").appendValue(date); + } + } + + /** + * Creates a matcher that matches when the examined string reprensents the same instant as the reference datetime + * @param date the reference datetime against which the examined string is checked + */ + public static ZonedDateTimeMatcher sameInstant(ZonedDateTime date) { + return new ZonedDateTimeMatcher(date); + } + + /** + * Verifies the equals/hashcode contract on the domain object. + */ + public static void equalsVerifier(Class clazz) throws Exception { + T domainObject1 = clazz.getConstructor().newInstance(); + assertThat(domainObject1.toString()).isNotNull(); + assertThat(domainObject1).isEqualTo(domainObject1); + assertThat(domainObject1.hashCode()).isEqualTo(domainObject1.hashCode()); + // Test with an instance of another class + Object testOtherObject = new Object(); + assertThat(domainObject1).isNotEqualTo(testOtherObject); + assertThat(domainObject1).isNotEqualTo(null); + // Test with an instance of the same class + T domainObject2 = clazz.getConstructor().newInstance(); + assertThat(domainObject1).isNotEqualTo(domainObject2); + // HashCodes are equals because the objects are not persisted yet + assertThat(domainObject1.hashCode()).isEqualTo(domainObject2.hashCode()); + } + + /** + * Create a FormattingConversionService which use ISO date format, instead of the localized one. + * @return the FormattingConversionService + */ + public static FormattingConversionService createFormattingConversionService() { + DefaultFormattingConversionService dfcs = new DefaultFormattingConversionService (); + DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); + registrar.setUseIsoFormat(true); + registrar.registerFormatters(dfcs); + return dfcs; + } + + private TestUtil() {} +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/UserJWTControllerIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/UserJWTControllerIntTest.java new file mode 100644 index 0000000000..3886710438 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/UserJWTControllerIntTest.java @@ -0,0 +1,125 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.repository.UserRepository; +import com.baeldung.jhipster5.security.jwt.TokenProvider; +import com.baeldung.jhipster5.web.rest.errors.ExceptionTranslator; +import com.baeldung.jhipster5.web.rest.vm.LoginVM; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; + +/** + * Test class for the UserJWTController REST controller. + * + * @see UserJWTController + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +public class UserJWTControllerIntTest { + + @Autowired + private TokenProvider tokenProvider; + + @Autowired + private AuthenticationManager authenticationManager; + + @Autowired + private UserRepository userRepository; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private ExceptionTranslator exceptionTranslator; + + private MockMvc mockMvc; + + @Before + public void setup() { + UserJWTController userJWTController = new UserJWTController(tokenProvider, authenticationManager); + this.mockMvc = MockMvcBuilders.standaloneSetup(userJWTController) + .setControllerAdvice(exceptionTranslator) + .build(); + } + + @Test + @Transactional + public void testAuthorize() throws Exception { + User user = new User(); + user.setLogin("user-jwt-controller"); + user.setEmail("user-jwt-controller@example.com"); + user.setActivated(true); + user.setPassword(passwordEncoder.encode("test")); + + userRepository.saveAndFlush(user); + + LoginVM login = new LoginVM(); + login.setUsername("user-jwt-controller"); + login.setPassword("test"); + mockMvc.perform(post("/api/authenticate") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(login))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id_token").isString()) + .andExpect(jsonPath("$.id_token").isNotEmpty()) + .andExpect(header().string("Authorization", not(nullValue()))) + .andExpect(header().string("Authorization", not(isEmptyString()))); + } + + @Test + @Transactional + public void testAuthorizeWithRememberMe() throws Exception { + User user = new User(); + user.setLogin("user-jwt-controller-remember-me"); + user.setEmail("user-jwt-controller-remember-me@example.com"); + user.setActivated(true); + user.setPassword(passwordEncoder.encode("test")); + + userRepository.saveAndFlush(user); + + LoginVM login = new LoginVM(); + login.setUsername("user-jwt-controller-remember-me"); + login.setPassword("test"); + login.setRememberMe(true); + mockMvc.perform(post("/api/authenticate") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(login))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.id_token").isString()) + .andExpect(jsonPath("$.id_token").isNotEmpty()) + .andExpect(header().string("Authorization", not(nullValue()))) + .andExpect(header().string("Authorization", not(isEmptyString()))); + } + + @Test + @Transactional + public void testAuthorizeFails() throws Exception { + LoginVM login = new LoginVM(); + login.setUsername("wrong-user"); + login.setPassword("wrong password"); + mockMvc.perform(post("/api/authenticate") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(login))) + .andExpect(status().isUnauthorized()) + .andExpect(jsonPath("$.id_token").doesNotExist()) + .andExpect(header().doesNotExist("Authorization")); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/UserResourceIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/UserResourceIntTest.java new file mode 100644 index 0000000000..d31df3b15c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/UserResourceIntTest.java @@ -0,0 +1,596 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.BookstoreApp; +import com.baeldung.jhipster5.domain.Authority; +import com.baeldung.jhipster5.domain.User; +import com.baeldung.jhipster5.repository.UserRepository; +import com.baeldung.jhipster5.security.AuthoritiesConstants; +import com.baeldung.jhipster5.service.MailService; +import com.baeldung.jhipster5.service.UserService; +import com.baeldung.jhipster5.service.dto.UserDTO; +import com.baeldung.jhipster5.service.mapper.UserMapper; +import com.baeldung.jhipster5.web.rest.errors.ExceptionTranslator; +import com.baeldung.jhipster5.web.rest.vm.ManagedUserVM; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.web.PageableHandlerMethodArgumentResolver; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; + +import javax.persistence.EntityManager; +import java.time.Instant; +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItems; +import static org.hamcrest.Matchers.hasItem; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +/** + * Test class for the UserResource REST controller. + * + * @see UserResource + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +public class UserResourceIntTest { + + private static final String DEFAULT_LOGIN = "johndoe"; + private static final String UPDATED_LOGIN = "jhipster"; + + private static final Long DEFAULT_ID = 1L; + + private static final String DEFAULT_PASSWORD = "passjohndoe"; + private static final String UPDATED_PASSWORD = "passjhipster"; + + private static final String DEFAULT_EMAIL = "johndoe@localhost"; + private static final String UPDATED_EMAIL = "jhipster@localhost"; + + private static final String DEFAULT_FIRSTNAME = "john"; + private static final String UPDATED_FIRSTNAME = "jhipsterFirstName"; + + private static final String DEFAULT_LASTNAME = "doe"; + private static final String UPDATED_LASTNAME = "jhipsterLastName"; + + private static final String DEFAULT_IMAGEURL = "http://placehold.it/50x50"; + private static final String UPDATED_IMAGEURL = "http://placehold.it/40x40"; + + private static final String DEFAULT_LANGKEY = "en"; + private static final String UPDATED_LANGKEY = "fr"; + + @Autowired + private UserRepository userRepository; + + @Autowired + private MailService mailService; + + @Autowired + private UserService userService; + + @Autowired + private UserMapper userMapper; + + @Autowired + private MappingJackson2HttpMessageConverter jacksonMessageConverter; + + @Autowired + private PageableHandlerMethodArgumentResolver pageableArgumentResolver; + + @Autowired + private ExceptionTranslator exceptionTranslator; + + @Autowired + private EntityManager em; + + private MockMvc restUserMockMvc; + + private User user; + + @Before + public void setup() { + UserResource userResource = new UserResource(userService, userRepository, mailService); + + this.restUserMockMvc = MockMvcBuilders.standaloneSetup(userResource) + .setCustomArgumentResolvers(pageableArgumentResolver) + .setControllerAdvice(exceptionTranslator) + .setMessageConverters(jacksonMessageConverter) + .build(); + } + + /** + * Create a User. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which has a required relationship to the User entity. + */ + public static User createEntity(EntityManager em) { + User user = new User(); + user.setLogin(DEFAULT_LOGIN + RandomStringUtils.randomAlphabetic(5)); + user.setPassword(RandomStringUtils.random(60)); + user.setActivated(true); + user.setEmail(RandomStringUtils.randomAlphabetic(5) + DEFAULT_EMAIL); + user.setFirstName(DEFAULT_FIRSTNAME); + user.setLastName(DEFAULT_LASTNAME); + user.setImageUrl(DEFAULT_IMAGEURL); + user.setLangKey(DEFAULT_LANGKEY); + return user; + } + + @Before + public void initTest() { + user = createEntity(em); + user.setLogin(DEFAULT_LOGIN); + user.setEmail(DEFAULT_EMAIL); + } + + @Test + @Transactional + public void createUser() throws Exception { + int databaseSizeBeforeCreate = userRepository.findAll().size(); + + // Create the User + ManagedUserVM managedUserVM = new ManagedUserVM(); + managedUserVM.setLogin(DEFAULT_LOGIN); + managedUserVM.setPassword(DEFAULT_PASSWORD); + managedUserVM.setFirstName(DEFAULT_FIRSTNAME); + managedUserVM.setLastName(DEFAULT_LASTNAME); + managedUserVM.setEmail(DEFAULT_EMAIL); + managedUserVM.setActivated(true); + managedUserVM.setImageUrl(DEFAULT_IMAGEURL); + managedUserVM.setLangKey(DEFAULT_LANGKEY); + managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + restUserMockMvc.perform(post("/api/users") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) + .andExpect(status().isCreated()); + + // Validate the User in the database + List userList = userRepository.findAll(); + assertThat(userList).hasSize(databaseSizeBeforeCreate + 1); + User testUser = userList.get(userList.size() - 1); + assertThat(testUser.getLogin()).isEqualTo(DEFAULT_LOGIN); + assertThat(testUser.getFirstName()).isEqualTo(DEFAULT_FIRSTNAME); + assertThat(testUser.getLastName()).isEqualTo(DEFAULT_LASTNAME); + assertThat(testUser.getEmail()).isEqualTo(DEFAULT_EMAIL); + assertThat(testUser.getImageUrl()).isEqualTo(DEFAULT_IMAGEURL); + assertThat(testUser.getLangKey()).isEqualTo(DEFAULT_LANGKEY); + } + + @Test + @Transactional + public void createUserWithExistingId() throws Exception { + int databaseSizeBeforeCreate = userRepository.findAll().size(); + + ManagedUserVM managedUserVM = new ManagedUserVM(); + managedUserVM.setId(1L); + managedUserVM.setLogin(DEFAULT_LOGIN); + managedUserVM.setPassword(DEFAULT_PASSWORD); + managedUserVM.setFirstName(DEFAULT_FIRSTNAME); + managedUserVM.setLastName(DEFAULT_LASTNAME); + managedUserVM.setEmail(DEFAULT_EMAIL); + managedUserVM.setActivated(true); + managedUserVM.setImageUrl(DEFAULT_IMAGEURL); + managedUserVM.setLangKey(DEFAULT_LANGKEY); + managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + // An entity with an existing ID cannot be created, so this API call must fail + restUserMockMvc.perform(post("/api/users") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) + .andExpect(status().isBadRequest()); + + // Validate the User in the database + List userList = userRepository.findAll(); + assertThat(userList).hasSize(databaseSizeBeforeCreate); + } + + @Test + @Transactional + public void createUserWithExistingLogin() throws Exception { + // Initialize the database + userRepository.saveAndFlush(user); + int databaseSizeBeforeCreate = userRepository.findAll().size(); + + ManagedUserVM managedUserVM = new ManagedUserVM(); + managedUserVM.setLogin(DEFAULT_LOGIN);// this login should already be used + managedUserVM.setPassword(DEFAULT_PASSWORD); + managedUserVM.setFirstName(DEFAULT_FIRSTNAME); + managedUserVM.setLastName(DEFAULT_LASTNAME); + managedUserVM.setEmail("anothermail@localhost"); + managedUserVM.setActivated(true); + managedUserVM.setImageUrl(DEFAULT_IMAGEURL); + managedUserVM.setLangKey(DEFAULT_LANGKEY); + managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + // Create the User + restUserMockMvc.perform(post("/api/users") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) + .andExpect(status().isBadRequest()); + + // Validate the User in the database + List userList = userRepository.findAll(); + assertThat(userList).hasSize(databaseSizeBeforeCreate); + } + + @Test + @Transactional + public void createUserWithExistingEmail() throws Exception { + // Initialize the database + userRepository.saveAndFlush(user); + int databaseSizeBeforeCreate = userRepository.findAll().size(); + + ManagedUserVM managedUserVM = new ManagedUserVM(); + managedUserVM.setLogin("anotherlogin"); + managedUserVM.setPassword(DEFAULT_PASSWORD); + managedUserVM.setFirstName(DEFAULT_FIRSTNAME); + managedUserVM.setLastName(DEFAULT_LASTNAME); + managedUserVM.setEmail(DEFAULT_EMAIL);// this email should already be used + managedUserVM.setActivated(true); + managedUserVM.setImageUrl(DEFAULT_IMAGEURL); + managedUserVM.setLangKey(DEFAULT_LANGKEY); + managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + // Create the User + restUserMockMvc.perform(post("/api/users") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) + .andExpect(status().isBadRequest()); + + // Validate the User in the database + List userList = userRepository.findAll(); + assertThat(userList).hasSize(databaseSizeBeforeCreate); + } + + @Test + @Transactional + public void getAllUsers() throws Exception { + // Initialize the database + userRepository.saveAndFlush(user); + + // Get all the users + restUserMockMvc.perform(get("/api/users?sort=id,desc") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(jsonPath("$.[*].login").value(hasItem(DEFAULT_LOGIN))) + .andExpect(jsonPath("$.[*].firstName").value(hasItem(DEFAULT_FIRSTNAME))) + .andExpect(jsonPath("$.[*].lastName").value(hasItem(DEFAULT_LASTNAME))) + .andExpect(jsonPath("$.[*].email").value(hasItem(DEFAULT_EMAIL))) + .andExpect(jsonPath("$.[*].imageUrl").value(hasItem(DEFAULT_IMAGEURL))) + .andExpect(jsonPath("$.[*].langKey").value(hasItem(DEFAULT_LANGKEY))); + } + + @Test + @Transactional + public void getUser() throws Exception { + // Initialize the database + userRepository.saveAndFlush(user); + + // Get the user + restUserMockMvc.perform(get("/api/users/{login}", user.getLogin())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(jsonPath("$.login").value(user.getLogin())) + .andExpect(jsonPath("$.firstName").value(DEFAULT_FIRSTNAME)) + .andExpect(jsonPath("$.lastName").value(DEFAULT_LASTNAME)) + .andExpect(jsonPath("$.email").value(DEFAULT_EMAIL)) + .andExpect(jsonPath("$.imageUrl").value(DEFAULT_IMAGEURL)) + .andExpect(jsonPath("$.langKey").value(DEFAULT_LANGKEY)); + } + + @Test + @Transactional + public void getNonExistingUser() throws Exception { + restUserMockMvc.perform(get("/api/users/unknown")) + .andExpect(status().isNotFound()); + } + + @Test + @Transactional + public void updateUser() throws Exception { + // Initialize the database + userRepository.saveAndFlush(user); + int databaseSizeBeforeUpdate = userRepository.findAll().size(); + + // Update the user + User updatedUser = userRepository.findById(user.getId()).get(); + + ManagedUserVM managedUserVM = new ManagedUserVM(); + managedUserVM.setId(updatedUser.getId()); + managedUserVM.setLogin(updatedUser.getLogin()); + managedUserVM.setPassword(UPDATED_PASSWORD); + managedUserVM.setFirstName(UPDATED_FIRSTNAME); + managedUserVM.setLastName(UPDATED_LASTNAME); + managedUserVM.setEmail(UPDATED_EMAIL); + managedUserVM.setActivated(updatedUser.getActivated()); + managedUserVM.setImageUrl(UPDATED_IMAGEURL); + managedUserVM.setLangKey(UPDATED_LANGKEY); + managedUserVM.setCreatedBy(updatedUser.getCreatedBy()); + managedUserVM.setCreatedDate(updatedUser.getCreatedDate()); + managedUserVM.setLastModifiedBy(updatedUser.getLastModifiedBy()); + managedUserVM.setLastModifiedDate(updatedUser.getLastModifiedDate()); + managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + restUserMockMvc.perform(put("/api/users") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) + .andExpect(status().isOk()); + + // Validate the User in the database + List userList = userRepository.findAll(); + assertThat(userList).hasSize(databaseSizeBeforeUpdate); + User testUser = userList.get(userList.size() - 1); + assertThat(testUser.getFirstName()).isEqualTo(UPDATED_FIRSTNAME); + assertThat(testUser.getLastName()).isEqualTo(UPDATED_LASTNAME); + assertThat(testUser.getEmail()).isEqualTo(UPDATED_EMAIL); + assertThat(testUser.getImageUrl()).isEqualTo(UPDATED_IMAGEURL); + assertThat(testUser.getLangKey()).isEqualTo(UPDATED_LANGKEY); + } + + @Test + @Transactional + public void updateUserLogin() throws Exception { + // Initialize the database + userRepository.saveAndFlush(user); + int databaseSizeBeforeUpdate = userRepository.findAll().size(); + + // Update the user + User updatedUser = userRepository.findById(user.getId()).get(); + + ManagedUserVM managedUserVM = new ManagedUserVM(); + managedUserVM.setId(updatedUser.getId()); + managedUserVM.setLogin(UPDATED_LOGIN); + managedUserVM.setPassword(UPDATED_PASSWORD); + managedUserVM.setFirstName(UPDATED_FIRSTNAME); + managedUserVM.setLastName(UPDATED_LASTNAME); + managedUserVM.setEmail(UPDATED_EMAIL); + managedUserVM.setActivated(updatedUser.getActivated()); + managedUserVM.setImageUrl(UPDATED_IMAGEURL); + managedUserVM.setLangKey(UPDATED_LANGKEY); + managedUserVM.setCreatedBy(updatedUser.getCreatedBy()); + managedUserVM.setCreatedDate(updatedUser.getCreatedDate()); + managedUserVM.setLastModifiedBy(updatedUser.getLastModifiedBy()); + managedUserVM.setLastModifiedDate(updatedUser.getLastModifiedDate()); + managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + restUserMockMvc.perform(put("/api/users") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) + .andExpect(status().isOk()); + + // Validate the User in the database + List userList = userRepository.findAll(); + assertThat(userList).hasSize(databaseSizeBeforeUpdate); + User testUser = userList.get(userList.size() - 1); + assertThat(testUser.getLogin()).isEqualTo(UPDATED_LOGIN); + assertThat(testUser.getFirstName()).isEqualTo(UPDATED_FIRSTNAME); + assertThat(testUser.getLastName()).isEqualTo(UPDATED_LASTNAME); + assertThat(testUser.getEmail()).isEqualTo(UPDATED_EMAIL); + assertThat(testUser.getImageUrl()).isEqualTo(UPDATED_IMAGEURL); + assertThat(testUser.getLangKey()).isEqualTo(UPDATED_LANGKEY); + } + + @Test + @Transactional + public void updateUserExistingEmail() throws Exception { + // Initialize the database with 2 users + userRepository.saveAndFlush(user); + + User anotherUser = new User(); + anotherUser.setLogin("jhipster"); + anotherUser.setPassword(RandomStringUtils.random(60)); + anotherUser.setActivated(true); + anotherUser.setEmail("jhipster@localhost"); + anotherUser.setFirstName("java"); + anotherUser.setLastName("hipster"); + anotherUser.setImageUrl(""); + anotherUser.setLangKey("en"); + userRepository.saveAndFlush(anotherUser); + + // Update the user + User updatedUser = userRepository.findById(user.getId()).get(); + + ManagedUserVM managedUserVM = new ManagedUserVM(); + managedUserVM.setId(updatedUser.getId()); + managedUserVM.setLogin(updatedUser.getLogin()); + managedUserVM.setPassword(updatedUser.getPassword()); + managedUserVM.setFirstName(updatedUser.getFirstName()); + managedUserVM.setLastName(updatedUser.getLastName()); + managedUserVM.setEmail("jhipster@localhost");// this email should already be used by anotherUser + managedUserVM.setActivated(updatedUser.getActivated()); + managedUserVM.setImageUrl(updatedUser.getImageUrl()); + managedUserVM.setLangKey(updatedUser.getLangKey()); + managedUserVM.setCreatedBy(updatedUser.getCreatedBy()); + managedUserVM.setCreatedDate(updatedUser.getCreatedDate()); + managedUserVM.setLastModifiedBy(updatedUser.getLastModifiedBy()); + managedUserVM.setLastModifiedDate(updatedUser.getLastModifiedDate()); + managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + restUserMockMvc.perform(put("/api/users") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) + .andExpect(status().isBadRequest()); + } + + @Test + @Transactional + public void updateUserExistingLogin() throws Exception { + // Initialize the database + userRepository.saveAndFlush(user); + + User anotherUser = new User(); + anotherUser.setLogin("jhipster"); + anotherUser.setPassword(RandomStringUtils.random(60)); + anotherUser.setActivated(true); + anotherUser.setEmail("jhipster@localhost"); + anotherUser.setFirstName("java"); + anotherUser.setLastName("hipster"); + anotherUser.setImageUrl(""); + anotherUser.setLangKey("en"); + userRepository.saveAndFlush(anotherUser); + + // Update the user + User updatedUser = userRepository.findById(user.getId()).get(); + + ManagedUserVM managedUserVM = new ManagedUserVM(); + managedUserVM.setId(updatedUser.getId()); + managedUserVM.setLogin("jhipster");// this login should already be used by anotherUser + managedUserVM.setPassword(updatedUser.getPassword()); + managedUserVM.setFirstName(updatedUser.getFirstName()); + managedUserVM.setLastName(updatedUser.getLastName()); + managedUserVM.setEmail(updatedUser.getEmail()); + managedUserVM.setActivated(updatedUser.getActivated()); + managedUserVM.setImageUrl(updatedUser.getImageUrl()); + managedUserVM.setLangKey(updatedUser.getLangKey()); + managedUserVM.setCreatedBy(updatedUser.getCreatedBy()); + managedUserVM.setCreatedDate(updatedUser.getCreatedDate()); + managedUserVM.setLastModifiedBy(updatedUser.getLastModifiedBy()); + managedUserVM.setLastModifiedDate(updatedUser.getLastModifiedDate()); + managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + restUserMockMvc.perform(put("/api/users") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) + .andExpect(status().isBadRequest()); + } + + @Test + @Transactional + public void deleteUser() throws Exception { + // Initialize the database + userRepository.saveAndFlush(user); + int databaseSizeBeforeDelete = userRepository.findAll().size(); + + // Delete the user + restUserMockMvc.perform(delete("/api/users/{login}", user.getLogin()) + .accept(TestUtil.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()); + + // Validate the database is empty + List userList = userRepository.findAll(); + assertThat(userList).hasSize(databaseSizeBeforeDelete - 1); + } + + @Test + @Transactional + public void getAllAuthorities() throws Exception { + restUserMockMvc.perform(get("/api/users/authorities") + .accept(TestUtil.APPLICATION_JSON_UTF8) + .contentType(TestUtil.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$").value(hasItems(AuthoritiesConstants.USER, AuthoritiesConstants.ADMIN))); + } + + @Test + @Transactional + public void testUserEquals() throws Exception { + TestUtil.equalsVerifier(User.class); + User user1 = new User(); + user1.setId(1L); + User user2 = new User(); + user2.setId(user1.getId()); + assertThat(user1).isEqualTo(user2); + user2.setId(2L); + assertThat(user1).isNotEqualTo(user2); + user1.setId(null); + assertThat(user1).isNotEqualTo(user2); + } + + @Test + public void testUserDTOtoUser() { + UserDTO userDTO = new UserDTO(); + userDTO.setId(DEFAULT_ID); + userDTO.setLogin(DEFAULT_LOGIN); + userDTO.setFirstName(DEFAULT_FIRSTNAME); + userDTO.setLastName(DEFAULT_LASTNAME); + userDTO.setEmail(DEFAULT_EMAIL); + userDTO.setActivated(true); + userDTO.setImageUrl(DEFAULT_IMAGEURL); + userDTO.setLangKey(DEFAULT_LANGKEY); + userDTO.setCreatedBy(DEFAULT_LOGIN); + userDTO.setLastModifiedBy(DEFAULT_LOGIN); + userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); + + User user = userMapper.userDTOToUser(userDTO); + assertThat(user.getId()).isEqualTo(DEFAULT_ID); + assertThat(user.getLogin()).isEqualTo(DEFAULT_LOGIN); + assertThat(user.getFirstName()).isEqualTo(DEFAULT_FIRSTNAME); + assertThat(user.getLastName()).isEqualTo(DEFAULT_LASTNAME); + assertThat(user.getEmail()).isEqualTo(DEFAULT_EMAIL); + assertThat(user.getActivated()).isEqualTo(true); + assertThat(user.getImageUrl()).isEqualTo(DEFAULT_IMAGEURL); + assertThat(user.getLangKey()).isEqualTo(DEFAULT_LANGKEY); + assertThat(user.getCreatedBy()).isNull(); + assertThat(user.getCreatedDate()).isNotNull(); + assertThat(user.getLastModifiedBy()).isNull(); + assertThat(user.getLastModifiedDate()).isNotNull(); + assertThat(user.getAuthorities()).extracting("name").containsExactly(AuthoritiesConstants.USER); + } + + @Test + public void testUserToUserDTO() { + user.setId(DEFAULT_ID); + user.setCreatedBy(DEFAULT_LOGIN); + user.setCreatedDate(Instant.now()); + user.setLastModifiedBy(DEFAULT_LOGIN); + user.setLastModifiedDate(Instant.now()); + Set authorities = new HashSet<>(); + Authority authority = new Authority(); + authority.setName(AuthoritiesConstants.USER); + authorities.add(authority); + user.setAuthorities(authorities); + + UserDTO userDTO = userMapper.userToUserDTO(user); + + assertThat(userDTO.getId()).isEqualTo(DEFAULT_ID); + assertThat(userDTO.getLogin()).isEqualTo(DEFAULT_LOGIN); + assertThat(userDTO.getFirstName()).isEqualTo(DEFAULT_FIRSTNAME); + assertThat(userDTO.getLastName()).isEqualTo(DEFAULT_LASTNAME); + assertThat(userDTO.getEmail()).isEqualTo(DEFAULT_EMAIL); + assertThat(userDTO.isActivated()).isEqualTo(true); + assertThat(userDTO.getImageUrl()).isEqualTo(DEFAULT_IMAGEURL); + assertThat(userDTO.getLangKey()).isEqualTo(DEFAULT_LANGKEY); + assertThat(userDTO.getCreatedBy()).isEqualTo(DEFAULT_LOGIN); + assertThat(userDTO.getCreatedDate()).isEqualTo(user.getCreatedDate()); + assertThat(userDTO.getLastModifiedBy()).isEqualTo(DEFAULT_LOGIN); + assertThat(userDTO.getLastModifiedDate()).isEqualTo(user.getLastModifiedDate()); + assertThat(userDTO.getAuthorities()).containsExactly(AuthoritiesConstants.USER); + assertThat(userDTO.toString()).isNotNull(); + } + + @Test + public void testAuthorityEquals() { + Authority authorityA = new Authority(); + assertThat(authorityA).isEqualTo(authorityA); + assertThat(authorityA).isNotEqualTo(null); + assertThat(authorityA).isNotEqualTo(new Object()); + assertThat(authorityA.hashCode()).isEqualTo(0); + assertThat(authorityA.toString()).isNotNull(); + + Authority authorityB = new Authority(); + assertThat(authorityA).isEqualTo(authorityB); + + authorityB.setName(AuthoritiesConstants.ADMIN); + assertThat(authorityA).isNotEqualTo(authorityB); + + authorityA.setName(AuthoritiesConstants.USER); + assertThat(authorityA).isNotEqualTo(authorityB); + + authorityB.setName(AuthoritiesConstants.USER); + assertThat(authorityA).isEqualTo(authorityB); + assertThat(authorityA.hashCode()).isEqualTo(authorityB.hashCode()); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslatorIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslatorIntTest.java new file mode 100644 index 0000000000..a94d54063b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslatorIntTest.java @@ -0,0 +1,150 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import com.baeldung.jhipster5.BookstoreApp; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * Test class for the ExceptionTranslator controller advice. + * + * @see ExceptionTranslator + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +public class ExceptionTranslatorIntTest { + + @Autowired + private ExceptionTranslatorTestController controller; + + @Autowired + private ExceptionTranslator exceptionTranslator; + + @Autowired + private MappingJackson2HttpMessageConverter jacksonMessageConverter; + + private MockMvc mockMvc; + + @Before + public void setup() { + mockMvc = MockMvcBuilders.standaloneSetup(controller) + .setControllerAdvice(exceptionTranslator) + .setMessageConverters(jacksonMessageConverter) + .build(); + } + + @Test + public void testConcurrencyFailure() throws Exception { + mockMvc.perform(get("/test/concurrency-failure")) + .andExpect(status().isConflict()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value(ErrorConstants.ERR_CONCURRENCY_FAILURE)); + } + + @Test + public void testMethodArgumentNotValid() throws Exception { + mockMvc.perform(post("/test/method-argument").content("{}").contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value(ErrorConstants.ERR_VALIDATION)) + .andExpect(jsonPath("$.fieldErrors.[0].objectName").value("testDTO")) + .andExpect(jsonPath("$.fieldErrors.[0].field").value("test")) + .andExpect(jsonPath("$.fieldErrors.[0].message").value("NotNull")); + } + + @Test + public void testParameterizedError() throws Exception { + mockMvc.perform(get("/test/parameterized-error")) + .andExpect(status().isBadRequest()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value("test parameterized error")) + .andExpect(jsonPath("$.params.param0").value("param0_value")) + .andExpect(jsonPath("$.params.param1").value("param1_value")); + } + + @Test + public void testParameterizedError2() throws Exception { + mockMvc.perform(get("/test/parameterized-error2")) + .andExpect(status().isBadRequest()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value("test parameterized error")) + .andExpect(jsonPath("$.params.foo").value("foo_value")) + .andExpect(jsonPath("$.params.bar").value("bar_value")); + } + + @Test + public void testMissingServletRequestPartException() throws Exception { + mockMvc.perform(get("/test/missing-servlet-request-part")) + .andExpect(status().isBadRequest()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value("error.http.400")); + } + + @Test + public void testMissingServletRequestParameterException() throws Exception { + mockMvc.perform(get("/test/missing-servlet-request-parameter")) + .andExpect(status().isBadRequest()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value("error.http.400")); + } + + @Test + public void testAccessDenied() throws Exception { + mockMvc.perform(get("/test/access-denied")) + .andExpect(status().isForbidden()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value("error.http.403")) + .andExpect(jsonPath("$.detail").value("test access denied!")); + } + + @Test + public void testUnauthorized() throws Exception { + mockMvc.perform(get("/test/unauthorized")) + .andExpect(status().isUnauthorized()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value("error.http.401")) + .andExpect(jsonPath("$.path").value("/test/unauthorized")) + .andExpect(jsonPath("$.detail").value("test authentication failed!")); + } + + @Test + public void testMethodNotSupported() throws Exception { + mockMvc.perform(post("/test/access-denied")) + .andExpect(status().isMethodNotAllowed()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value("error.http.405")) + .andExpect(jsonPath("$.detail").value("Request method 'POST' not supported")); + } + + @Test + public void testExceptionWithResponseStatus() throws Exception { + mockMvc.perform(get("/test/response-status")) + .andExpect(status().isBadRequest()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value("error.http.400")) + .andExpect(jsonPath("$.title").value("test response status")); + } + + @Test + public void testInternalServerError() throws Exception { + mockMvc.perform(get("/test/internal-server-error")) + .andExpect(status().isInternalServerError()) + .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) + .andExpect(jsonPath("$.message").value("error.http.500")) + .andExpect(jsonPath("$.title").value("Internal Server Error")); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslatorTestController.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslatorTestController.java new file mode 100644 index 0000000000..f8d84151b9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/errors/ExceptionTranslatorTestController.java @@ -0,0 +1,86 @@ +package com.baeldung.jhipster5.web.rest.errors; + +import org.springframework.dao.ConcurrencyFailureException; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import java.util.HashMap; +import java.util.Map; + +@RestController +public class ExceptionTranslatorTestController { + + @GetMapping("/test/concurrency-failure") + public void concurrencyFailure() { + throw new ConcurrencyFailureException("test concurrency failure"); + } + + @PostMapping("/test/method-argument") + public void methodArgument(@Valid @RequestBody TestDTO testDTO) { + } + + @GetMapping("/test/parameterized-error") + public void parameterizedError() { + throw new CustomParameterizedException("test parameterized error", "param0_value", "param1_value"); + } + + @GetMapping("/test/parameterized-error2") + public void parameterizedError2() { + Map params = new HashMap<>(); + params.put("foo", "foo_value"); + params.put("bar", "bar_value"); + throw new CustomParameterizedException("test parameterized error", params); + } + + @GetMapping("/test/missing-servlet-request-part") + public void missingServletRequestPartException(@RequestPart String part) { + } + + @GetMapping("/test/missing-servlet-request-parameter") + public void missingServletRequestParameterException(@RequestParam String param) { + } + + @GetMapping("/test/access-denied") + public void accessdenied() { + throw new AccessDeniedException("test access denied!"); + } + + @GetMapping("/test/unauthorized") + public void unauthorized() { + throw new BadCredentialsException("test authentication failed!"); + } + + @GetMapping("/test/response-status") + public void exceptionWithReponseStatus() { + throw new TestResponseStatusException(); + } + + @GetMapping("/test/internal-server-error") + public void internalServerError() { + throw new RuntimeException(); + } + + public static class TestDTO { + + @NotNull + private String test; + + public String getTest() { + return test; + } + + public void setTest(String test) { + this.test = test; + } + } + + @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "test response status") + @SuppressWarnings("serial") + public static class TestResponseStatusException extends RuntimeException { + } + +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/util/PaginationUtilUnitTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/util/PaginationUtilUnitTest.java new file mode 100644 index 0000000000..78b17ee859 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/util/PaginationUtilUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.jhipster5.web.rest.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpHeaders; + +/** + * Tests based on parsing algorithm in app/components/util/pagination-util.service.js + * + * @see PaginationUtil + */ +public class PaginationUtilUnitTest { + + @Test + public void generatePaginationHttpHeadersTest() { + String baseUrl = "/api/_search/example"; + List content = new ArrayList<>(); + Page page = new PageImpl<>(content, PageRequest.of(6, 50), 400L); + HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, baseUrl); + List strHeaders = headers.get(HttpHeaders.LINK); + assertNotNull(strHeaders); + assertTrue(strHeaders.size() == 1); + String headerData = strHeaders.get(0); + assertTrue(headerData.split(",").length == 4); + String expectedData = "; rel=\"next\"," + + "; rel=\"prev\"," + + "; rel=\"last\"," + + "; rel=\"first\""; + assertEquals(expectedData, headerData); + List xTotalCountHeaders = headers.get("X-Total-Count"); + assertTrue(xTotalCountHeaders.size() == 1); + assertTrue(Long.valueOf(xTotalCountHeaders.get(0)).equals(400L)); + } + +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/jest-global-mocks.ts b/jhipster-5/bookstore-monolith/src/test/javascript/jest-global-mocks.ts new file mode 100644 index 0000000000..a998259857 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/jest-global-mocks.ts @@ -0,0 +1,15 @@ +const mock = () => { + let storage = {}; + return { + getItem: key => (key in storage ? storage[key] : null), + setItem: (key, value) => (storage[key] = value || ''), + removeItem: key => delete storage[key], + clear: () => (storage = {}) + }; +}; + +Object.defineProperty(window, 'localStorage', { value: mock() }); +Object.defineProperty(window, 'sessionStorage', { value: mock() }); +Object.defineProperty(window, 'getComputedStyle', { + value: () => ['-webkit-appearance'] +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/jest.conf.js b/jhipster-5/bookstore-monolith/src/test/javascript/jest.conf.js new file mode 100644 index 0000000000..05054a94b8 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/jest.conf.js @@ -0,0 +1,26 @@ +module.exports = { + preset: 'jest-preset-angular', + setupTestFrameworkScriptFile: '/src/test/javascript/jest.ts', + coverageDirectory: '/target/test-results/', + globals: { + 'ts-jest': { + tsConfigFile: 'tsconfig.json' + }, + __TRANSFORM_HTML__: true + }, + coveragePathIgnorePatterns: [ + '/src/test/javascript' + ], + moduleNameMapper: { + 'app/(.*)': '/src/main/webapp/app/$1' + }, + reporters: [ + 'default', + [ 'jest-junit', { output: './target/test-results/TESTS-results-jest.xml' } ] + ], + testResultsProcessor: 'jest-sonar-reporter', + transformIgnorePatterns: ['node_modules/(?!@angular/common/locales)'], + testMatch: ['/src/test/javascript/spec/**/+(*.)+(spec.ts)'], + rootDir: '../../../', + testURL: "http://localhost/" +}; diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/jest.ts b/jhipster-5/bookstore-monolith/src/test/javascript/jest.ts new file mode 100644 index 0000000000..904329f538 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/jest.ts @@ -0,0 +1,2 @@ +import 'jest-preset-angular'; +import './jest-global-mocks'; diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/activate/activate.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/activate/activate.component.spec.ts new file mode 100644 index 0000000000..87a550e8ef --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/activate/activate.component.spec.ts @@ -0,0 +1,72 @@ +import { TestBed, async, tick, fakeAsync, inject } from '@angular/core/testing'; +import { ActivatedRoute } from '@angular/router'; +import { Observable, of, throwError } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { MockActivatedRoute } from '../../../helpers/mock-route.service'; +import { ActivateService } from 'app/account/activate/activate.service'; +import { ActivateComponent } from 'app/account/activate/activate.component'; + +describe('Component Tests', () => { + describe('ActivateComponent', () => { + let comp: ActivateComponent; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [ActivateComponent], + providers: [ + { + provide: ActivatedRoute, + useValue: new MockActivatedRoute({ key: 'ABC123' }) + } + ] + }) + .overrideTemplate(ActivateComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + const fixture = TestBed.createComponent(ActivateComponent); + comp = fixture.componentInstance; + }); + + it('calls activate.get with the key from params', inject( + [ActivateService], + fakeAsync((service: ActivateService) => { + spyOn(service, 'get').and.returnValue(of()); + + comp.ngOnInit(); + tick(); + + expect(service.get).toHaveBeenCalledWith('ABC123'); + }) + )); + + it('should set set success to OK upon successful activation', inject( + [ActivateService], + fakeAsync((service: ActivateService) => { + spyOn(service, 'get').and.returnValue(of({})); + + comp.ngOnInit(); + tick(); + + expect(comp.error).toBe(null); + expect(comp.success).toEqual('OK'); + }) + )); + + it('should set set error to ERROR upon activation failure', inject( + [ActivateService], + fakeAsync((service: ActivateService) => { + spyOn(service, 'get').and.returnValue(throwError('ERROR')); + + comp.ngOnInit(); + tick(); + + expect(comp.error).toBe('ERROR'); + expect(comp.success).toEqual(null); + }) + )); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password-reset/finish/password-reset-finish.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password-reset/finish/password-reset-finish.component.spec.ts new file mode 100644 index 0000000000..36a3b8db65 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password-reset/finish/password-reset-finish.component.spec.ts @@ -0,0 +1,119 @@ +import { ComponentFixture, TestBed, inject, tick, fakeAsync } from '@angular/core/testing'; +import { Observable, of, throwError } from 'rxjs'; +import { Renderer, ElementRef } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { BookstoreTestModule } from '../../../../test.module'; +import { PasswordResetFinishComponent } from 'app/account/password-reset/finish/password-reset-finish.component'; +import { PasswordResetFinishService } from 'app/account/password-reset/finish/password-reset-finish.service'; +import { MockActivatedRoute } from '../../../../helpers/mock-route.service'; + +describe('Component Tests', () => { + describe('PasswordResetFinishComponent', () => { + let fixture: ComponentFixture; + let comp: PasswordResetFinishComponent; + + beforeEach(() => { + fixture = TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [PasswordResetFinishComponent], + providers: [ + { + provide: ActivatedRoute, + useValue: new MockActivatedRoute({ key: 'XYZPDQ' }) + }, + { + provide: Renderer, + useValue: { + invokeElementMethod(renderElement: any, methodName: string, args?: any[]) {} + } + }, + { + provide: ElementRef, + useValue: new ElementRef(null) + } + ] + }) + .overrideTemplate(PasswordResetFinishComponent, '') + .createComponent(PasswordResetFinishComponent); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PasswordResetFinishComponent); + comp = fixture.componentInstance; + comp.ngOnInit(); + }); + + it('should define its initial state', () => { + comp.ngOnInit(); + + expect(comp.keyMissing).toBeFalsy(); + expect(comp.key).toEqual('XYZPDQ'); + expect(comp.resetAccount).toEqual({}); + }); + + it('sets focus after the view has been initialized', inject([ElementRef], (elementRef: ElementRef) => { + const element = fixture.nativeElement; + const node = { + focus() {} + }; + + elementRef.nativeElement = element; + spyOn(element, 'querySelector').and.returnValue(node); + spyOn(node, 'focus'); + + comp.ngAfterViewInit(); + + expect(element.querySelector).toHaveBeenCalledWith('#password'); + expect(node.focus).toHaveBeenCalled(); + })); + + it('should ensure the two passwords entered match', () => { + comp.resetAccount.password = 'password'; + comp.confirmPassword = 'non-matching'; + + comp.finishReset(); + + expect(comp.doNotMatch).toEqual('ERROR'); + }); + + it('should update success to OK after resetting password', inject( + [PasswordResetFinishService], + fakeAsync((service: PasswordResetFinishService) => { + spyOn(service, 'save').and.returnValue(of({})); + + comp.resetAccount.password = 'password'; + comp.confirmPassword = 'password'; + + comp.finishReset(); + tick(); + + expect(service.save).toHaveBeenCalledWith({ + key: 'XYZPDQ', + newPassword: 'password' + }); + expect(comp.success).toEqual('OK'); + }) + )); + + it('should notify of generic error', inject( + [PasswordResetFinishService], + fakeAsync((service: PasswordResetFinishService) => { + spyOn(service, 'save').and.returnValue(throwError('ERROR')); + + comp.resetAccount.password = 'password'; + comp.confirmPassword = 'password'; + + comp.finishReset(); + tick(); + + expect(service.save).toHaveBeenCalledWith({ + key: 'XYZPDQ', + newPassword: 'password' + }); + expect(comp.success).toBeNull(); + expect(comp.error).toEqual('ERROR'); + }) + )); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password-reset/init/password-reset-init.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password-reset/init/password-reset-init.component.spec.ts new file mode 100644 index 0000000000..f121a4dd27 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password-reset/init/password-reset-init.component.spec.ts @@ -0,0 +1,110 @@ +import { ComponentFixture, TestBed, inject } from '@angular/core/testing'; +import { Renderer, ElementRef } from '@angular/core'; +import { Observable, of, throwError } from 'rxjs'; + +import { BookstoreTestModule } from '../../../../test.module'; +import { PasswordResetInitComponent } from 'app/account/password-reset/init/password-reset-init.component'; +import { PasswordResetInitService } from 'app/account/password-reset/init/password-reset-init.service'; +import { EMAIL_NOT_FOUND_TYPE } from 'app/shared'; + +describe('Component Tests', () => { + describe('PasswordResetInitComponent', () => { + let fixture: ComponentFixture; + let comp: PasswordResetInitComponent; + + beforeEach(() => { + fixture = TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [PasswordResetInitComponent], + providers: [ + { + provide: Renderer, + useValue: { + invokeElementMethod(renderElement: any, methodName: string, args?: any[]) {} + } + }, + { + provide: ElementRef, + useValue: new ElementRef(null) + } + ] + }) + .overrideTemplate(PasswordResetInitComponent, '') + .createComponent(PasswordResetInitComponent); + comp = fixture.componentInstance; + comp.ngOnInit(); + }); + + it('should define its initial state', () => { + expect(comp.success).toBeUndefined(); + expect(comp.error).toBeUndefined(); + expect(comp.errorEmailNotExists).toBeUndefined(); + expect(comp.resetAccount).toEqual({}); + }); + + it('sets focus after the view has been initialized', inject([ElementRef], (elementRef: ElementRef) => { + const element = fixture.nativeElement; + const node = { + focus() {} + }; + + elementRef.nativeElement = element; + spyOn(element, 'querySelector').and.returnValue(node); + spyOn(node, 'focus'); + + comp.ngAfterViewInit(); + + expect(element.querySelector).toHaveBeenCalledWith('#email'); + expect(node.focus).toHaveBeenCalled(); + })); + + it('notifies of success upon successful requestReset', inject([PasswordResetInitService], (service: PasswordResetInitService) => { + spyOn(service, 'save').and.returnValue(of({})); + comp.resetAccount.email = 'user@domain.com'; + + comp.requestReset(); + + expect(service.save).toHaveBeenCalledWith('user@domain.com'); + expect(comp.success).toEqual('OK'); + expect(comp.error).toBeNull(); + expect(comp.errorEmailNotExists).toBeNull(); + })); + + it('notifies of unknown email upon email address not registered/400', inject( + [PasswordResetInitService], + (service: PasswordResetInitService) => { + spyOn(service, 'save').and.returnValue( + throwError({ + status: 400, + error: { type: EMAIL_NOT_FOUND_TYPE } + }) + ); + comp.resetAccount.email = 'user@domain.com'; + + comp.requestReset(); + + expect(service.save).toHaveBeenCalledWith('user@domain.com'); + expect(comp.success).toBeNull(); + expect(comp.error).toBeNull(); + expect(comp.errorEmailNotExists).toEqual('ERROR'); + } + )); + + it('notifies of error upon error response', inject([PasswordResetInitService], (service: PasswordResetInitService) => { + spyOn(service, 'save').and.returnValue( + throwError({ + status: 503, + data: 'something else' + }) + ); + comp.resetAccount.email = 'user@domain.com'; + + comp.requestReset(); + + expect(service.save).toHaveBeenCalledWith('user@domain.com'); + expect(comp.success).toBeNull(); + expect(comp.errorEmailNotExists).toBeNull(); + expect(comp.error).toEqual('ERROR'); + })); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password/password-strength-bar.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password/password-strength-bar.component.spec.ts new file mode 100644 index 0000000000..35e923ac00 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password/password-strength-bar.component.spec.ts @@ -0,0 +1,48 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; + +import { PasswordStrengthBarComponent } from 'app/account/password/password-strength-bar.component'; + +describe('Component Tests', () => { + describe('PasswordStrengthBarComponent', () => { + let comp: PasswordStrengthBarComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [PasswordStrengthBarComponent] + }) + .overrideTemplate(PasswordStrengthBarComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PasswordStrengthBarComponent); + comp = fixture.componentInstance; + }); + + describe('PasswordStrengthBarComponents', () => { + it('should initialize with default values', () => { + expect(comp.measureStrength('')).toBe(0); + expect(comp.colors).toEqual(['#F00', '#F90', '#FF0', '#9F0', '#0F0']); + expect(comp.getColor(0).idx).toBe(1); + expect(comp.getColor(0).col).toBe(comp.colors[0]); + }); + + it('should increase strength upon password value change', () => { + expect(comp.measureStrength('')).toBe(0); + expect(comp.measureStrength('aa')).toBeGreaterThanOrEqual(comp.measureStrength('')); + expect(comp.measureStrength('aa^6')).toBeGreaterThanOrEqual(comp.measureStrength('aa')); + expect(comp.measureStrength('Aa090(**)')).toBeGreaterThanOrEqual(comp.measureStrength('aa^6')); + expect(comp.measureStrength('Aa090(**)+-07365')).toBeGreaterThanOrEqual(comp.measureStrength('Aa090(**)')); + }); + + it('should change the color based on strength', () => { + expect(comp.getColor(0).col).toBe(comp.colors[0]); + expect(comp.getColor(11).col).toBe(comp.colors[1]); + expect(comp.getColor(22).col).toBe(comp.colors[2]); + expect(comp.getColor(33).col).toBe(comp.colors[3]); + expect(comp.getColor(44).col).toBe(comp.colors[4]); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password/password.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password/password.component.spec.ts new file mode 100644 index 0000000000..86edf940bd --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/password/password.component.spec.ts @@ -0,0 +1,89 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { HttpResponse } from '@angular/common/http'; +import { Observable, of, throwError } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { PasswordComponent } from 'app/account/password/password.component'; +import { PasswordService } from 'app/account/password/password.service'; + +describe('Component Tests', () => { + describe('PasswordComponent', () => { + let comp: PasswordComponent; + let fixture: ComponentFixture; + let service: PasswordService; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [PasswordComponent], + providers: [] + }) + .overrideTemplate(PasswordComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PasswordComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(PasswordService); + }); + + it('should show error if passwords do not match', () => { + // GIVEN + comp.newPassword = 'password1'; + comp.confirmPassword = 'password2'; + // WHEN + comp.changePassword(); + // THEN + expect(comp.doNotMatch).toBe('ERROR'); + expect(comp.error).toBeNull(); + expect(comp.success).toBeNull(); + }); + + it('should call Auth.changePassword when passwords match', () => { + // GIVEN + const passwordValues = { + currentPassword: 'oldPassword', + newPassword: 'myPassword' + }; + + spyOn(service, 'save').and.returnValue(of(new HttpResponse({ body: true }))); + comp.currentPassword = passwordValues.currentPassword; + comp.newPassword = comp.confirmPassword = passwordValues.newPassword; + + // WHEN + comp.changePassword(); + + // THEN + expect(service.save).toHaveBeenCalledWith(passwordValues.newPassword, passwordValues.currentPassword); + }); + + it('should set success to OK upon success', function() { + // GIVEN + spyOn(service, 'save').and.returnValue(of(new HttpResponse({ body: true }))); + comp.newPassword = comp.confirmPassword = 'myPassword'; + + // WHEN + comp.changePassword(); + + // THEN + expect(comp.doNotMatch).toBeNull(); + expect(comp.error).toBeNull(); + expect(comp.success).toBe('OK'); + }); + + it('should notify of error if change password fails', function() { + // GIVEN + spyOn(service, 'save').and.returnValue(throwError('ERROR')); + comp.newPassword = comp.confirmPassword = 'myPassword'; + + // WHEN + comp.changePassword(); + + // THEN + expect(comp.doNotMatch).toBeNull(); + expect(comp.success).toBeNull(); + expect(comp.error).toBe('ERROR'); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/register/register.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/register/register.component.spec.ts new file mode 100644 index 0000000000..ae02abbb91 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/register/register.component.spec.ts @@ -0,0 +1,118 @@ +import { ComponentFixture, TestBed, async, inject, tick, fakeAsync } from '@angular/core/testing'; +import { Observable, of, throwError } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { EMAIL_ALREADY_USED_TYPE, LOGIN_ALREADY_USED_TYPE } from 'app/shared'; +import { Register } from 'app/account/register/register.service'; +import { RegisterComponent } from 'app/account/register/register.component'; + +describe('Component Tests', () => { + describe('RegisterComponent', () => { + let fixture: ComponentFixture; + let comp: RegisterComponent; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [RegisterComponent] + }) + .overrideTemplate(RegisterComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(RegisterComponent); + comp = fixture.componentInstance; + comp.ngOnInit(); + }); + + it('should ensure the two passwords entered match', () => { + comp.registerAccount.password = 'password'; + comp.confirmPassword = 'non-matching'; + + comp.register(); + + expect(comp.doNotMatch).toEqual('ERROR'); + }); + + it('should update success to OK after creating an account', inject( + [Register], + fakeAsync((service: Register) => { + spyOn(service, 'save').and.returnValue(of({})); + comp.registerAccount.password = comp.confirmPassword = 'password'; + + comp.register(); + tick(); + + expect(service.save).toHaveBeenCalledWith({ + password: 'password', + langKey: 'en' + }); + expect(comp.success).toEqual(true); + expect(comp.registerAccount.langKey).toEqual('en'); + expect(comp.errorUserExists).toBeNull(); + expect(comp.errorEmailExists).toBeNull(); + expect(comp.error).toBeNull(); + }) + )); + + it('should notify of user existence upon 400/login already in use', inject( + [Register], + fakeAsync((service: Register) => { + spyOn(service, 'save').and.returnValue( + throwError({ + status: 400, + error: { type: LOGIN_ALREADY_USED_TYPE } + }) + ); + comp.registerAccount.password = comp.confirmPassword = 'password'; + + comp.register(); + tick(); + + expect(comp.errorUserExists).toEqual('ERROR'); + expect(comp.errorEmailExists).toBeNull(); + expect(comp.error).toBeNull(); + }) + )); + + it('should notify of email existence upon 400/email address already in use', inject( + [Register], + fakeAsync((service: Register) => { + spyOn(service, 'save').and.returnValue( + throwError({ + status: 400, + error: { type: EMAIL_ALREADY_USED_TYPE } + }) + ); + comp.registerAccount.password = comp.confirmPassword = 'password'; + + comp.register(); + tick(); + + expect(comp.errorEmailExists).toEqual('ERROR'); + expect(comp.errorUserExists).toBeNull(); + expect(comp.error).toBeNull(); + }) + )); + + it('should notify of generic error', inject( + [Register], + fakeAsync((service: Register) => { + spyOn(service, 'save').and.returnValue( + throwError({ + status: 503 + }) + ); + comp.registerAccount.password = comp.confirmPassword = 'password'; + + comp.register(); + tick(); + + expect(comp.errorUserExists).toBeNull(); + expect(comp.errorEmailExists).toBeNull(); + expect(comp.error).toEqual('ERROR'); + }) + )); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/settings/settings.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/settings/settings.component.spec.ts new file mode 100644 index 0000000000..b6a6d34c19 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/account/settings/settings.component.spec.ts @@ -0,0 +1,81 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { Observable, throwError } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { AccountService } from 'app/core'; +import { SettingsComponent } from 'app/account/settings/settings.component'; + +describe('Component Tests', () => { + describe('SettingsComponent', () => { + let comp: SettingsComponent; + let fixture: ComponentFixture; + let mockAuth: any; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [SettingsComponent], + providers: [] + }) + .overrideTemplate(SettingsComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SettingsComponent); + comp = fixture.componentInstance; + mockAuth = fixture.debugElement.injector.get(AccountService); + }); + + it('should send the current identity upon save', () => { + // GIVEN + const accountValues = { + firstName: 'John', + lastName: 'Doe', + + activated: true, + email: 'john.doe@mail.com', + langKey: 'en', + login: 'john' + }; + mockAuth.setIdentityResponse(accountValues); + + // WHEN + comp.settingsAccount = accountValues; + comp.save(); + + // THEN + expect(mockAuth.identitySpy).toHaveBeenCalled(); + expect(mockAuth.saveSpy).toHaveBeenCalledWith(accountValues); + expect(comp.settingsAccount).toEqual(accountValues); + }); + + it('should notify of success upon successful save', () => { + // GIVEN + const accountValues = { + firstName: 'John', + lastName: 'Doe' + }; + mockAuth.setIdentityResponse(accountValues); + + // WHEN + comp.save(); + + // THEN + expect(comp.error).toBeNull(); + expect(comp.success).toBe('OK'); + }); + + it('should notify of error upon failed save', () => { + // GIVEN + mockAuth.saveSpy.and.returnValue(throwError('ERROR')); + + // WHEN + comp.save(); + + // THEN + expect(comp.error).toEqual('ERROR'); + expect(comp.success).toBeNull(); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/audits/audits.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/audits/audits.component.spec.ts new file mode 100644 index 0000000000..254791f51a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/audits/audits.component.spec.ts @@ -0,0 +1,133 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { Observable, of } from 'rxjs'; +import { HttpHeaders, HttpResponse } from '@angular/common/http'; + +import { BookstoreTestModule } from '../../../test.module'; +import { AuditsComponent } from 'app/admin/audits/audits.component'; +import { AuditsService } from 'app/admin/audits/audits.service'; +import { Audit } from 'app/admin/audits/audit.model'; +import { ITEMS_PER_PAGE } from 'app/shared'; + +function build2DigitsDatePart(datePart: number) { + return `0${datePart}`.slice(-2); +} + +function getDate(isToday = true) { + let date: Date = new Date(); + if (isToday) { + // Today + 1 day - needed if the current day must be included + date.setDate(date.getDate() + 1); + } else { + // get last month + if (date.getMonth() === 0) { + date = new Date(date.getFullYear() - 1, 11, date.getDate()); + } else { + date = new Date(date.getFullYear(), date.getMonth() - 1, date.getDate()); + } + } + const monthString = build2DigitsDatePart(date.getMonth() + 1); + const dateString = build2DigitsDatePart(date.getDate()); + return `${date.getFullYear()}-${monthString}-${dateString}`; +} + +describe('Component Tests', () => { + describe('AuditsComponent', () => { + let comp: AuditsComponent; + let fixture: ComponentFixture; + let service: AuditsService; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [AuditsComponent], + providers: [AuditsService] + }) + .overrideTemplate(AuditsComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AuditsComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(AuditsService); + }); + + describe('today function ', () => { + it('should set toDate to current date', () => { + comp.today(); + expect(comp.toDate).toBe(getDate()); + }); + }); + + describe('previousMonth function ', () => { + it('should set fromDate to current date', () => { + comp.previousMonth(); + expect(comp.fromDate).toBe(getDate(false)); + }); + }); + + describe('By default, on init', () => { + it('should set all default values correctly', () => { + fixture.detectChanges(); + expect(comp.toDate).toBe(getDate()); + expect(comp.fromDate).toBe(getDate(false)); + expect(comp.itemsPerPage).toBe(ITEMS_PER_PAGE); + expect(comp.page).toBe(10); + expect(comp.reverse).toBeFalsy(); + expect(comp.predicate).toBe('id'); + }); + }); + + describe('OnInit', () => { + it('Should call load all on init', () => { + // GIVEN + const headers = new HttpHeaders().append('link', 'link;link'); + const audit = new Audit({ remoteAddress: '127.0.0.1', sessionId: '123' }, 'user', '20140101', 'AUTHENTICATION_SUCCESS'); + spyOn(service, 'query').and.returnValue( + of( + new HttpResponse({ + body: [audit], + headers + }) + ) + ); + + // WHEN + comp.ngOnInit(); + + // THEN + expect(service.query).toHaveBeenCalled(); + expect(comp.audits[0]).toEqual(jasmine.objectContaining(audit)); + }); + }); + + describe('Create sort object', () => { + it('Should sort only by id asc', () => { + // GIVEN + comp.predicate = 'id'; + comp.reverse = false; + + // WHEN + const sort = comp.sort(); + + // THEN + expect(sort.length).toEqual(1); + expect(sort[0]).toEqual('id,desc'); + }); + + it('Should sort by timestamp asc then by id', () => { + // GIVEN + comp.predicate = 'timestamp'; + comp.reverse = true; + + // WHEN + const sort = comp.sort(); + + // THEN + expect(sort.length).toEqual(2); + expect(sort[0]).toEqual('timestamp,asc'); + expect(sort[1]).toEqual('id'); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/audits/audits.service.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/audits/audits.service.spec.ts new file mode 100644 index 0000000000..84ff79f633 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/audits/audits.service.spec.ts @@ -0,0 +1,59 @@ +import { TestBed } from '@angular/core/testing'; + +import { AuditsService } from 'app/admin/audits/audits.service'; +import { Audit } from 'app/admin/audits/audit.model'; +import { SERVER_API_URL } from 'app/app.constants'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; + +describe('Service Tests', () => { + describe('Audits Service', () => { + let service: AuditsService; + let httpMock; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule] + }); + + service = TestBed.get(AuditsService); + httpMock = TestBed.get(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + }); + + describe('Service methods', () => { + it('should call correct URL', () => { + service.query({}).subscribe(() => {}); + + const req = httpMock.expectOne({ method: 'GET' }); + const resourceUrl = SERVER_API_URL + 'management/audits'; + expect(req.request.url).toEqual(resourceUrl); + }); + + it('should return Audits', () => { + const audit = new Audit({ remoteAddress: '127.0.0.1', sessionId: '123' }, 'user', '20140101', 'AUTHENTICATION_SUCCESS'); + + service.query({}).subscribe(received => { + expect(received.body[0]).toEqual(audit); + }); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush([audit]); + }); + + it('should propagate not found response', () => { + service.query({}).subscribe(null, (_error: any) => { + expect(_error.status).toEqual(404); + }); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush('Invalid request parameters', { + status: 404, + statusText: 'Bad Request' + }); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/configuration/configuration.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/configuration/configuration.component.spec.ts new file mode 100644 index 0000000000..d21f87b57b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/configuration/configuration.component.spec.ts @@ -0,0 +1,71 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { of } from 'rxjs'; +import { HttpHeaders, HttpResponse } from '@angular/common/http'; + +import { BookstoreTestModule } from '../../../test.module'; +import { JhiConfigurationComponent } from 'app/admin/configuration/configuration.component'; +import { JhiConfigurationService } from 'app/admin/configuration/configuration.service'; +import { ITEMS_PER_PAGE } from 'app/shared'; +import { Log } from 'app/admin'; + +describe('Component Tests', () => { + describe('JhiConfigurationComponent', () => { + let comp: JhiConfigurationComponent; + let fixture: ComponentFixture; + let service: JhiConfigurationService; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [JhiConfigurationComponent], + providers: [JhiConfigurationService] + }) + .overrideTemplate(JhiConfigurationComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(JhiConfigurationComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(JhiConfigurationService); + }); + + describe('OnInit', () => { + it('should set all default values correctly', () => { + expect(comp.configKeys).toEqual([]); + expect(comp.filter).toBe(''); + expect(comp.orderProp).toBe('prefix'); + expect(comp.reverse).toBe(false); + }); + it('Should call load all on init', () => { + // GIVEN + const body = [{ config: 'test', properties: 'test' }, { config: 'test2' }]; + const envConfig = { envConfig: 'test' }; + spyOn(service, 'get').and.returnValue(of(body)); + spyOn(service, 'getEnv').and.returnValue(of(envConfig)); + + // WHEN + comp.ngOnInit(); + + // THEN + expect(service.get).toHaveBeenCalled(); + expect(service.getEnv).toHaveBeenCalled(); + expect(comp.configKeys).toEqual([['0', '1', '2', '3']]); + expect(comp.allConfiguration).toEqual(envConfig); + }); + }); + describe('keys method', () => { + it('should return the keys of an Object', () => { + // GIVEN + const data = { + key1: 'test', + key2: 'test2' + }; + + // THEN + expect(comp.keys(data)).toEqual(['key1', 'key2']); + expect(comp.keys(undefined)).toEqual([]); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/configuration/configuration.service.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/configuration/configuration.service.spec.ts new file mode 100644 index 0000000000..6039044b7f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/configuration/configuration.service.spec.ts @@ -0,0 +1,64 @@ +import { TestBed } from '@angular/core/testing'; + +import { JhiConfigurationService } from 'app/admin/configuration/configuration.service'; +import { SERVER_API_URL } from 'app/app.constants'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { HttpResponse } from '@angular/common/http'; + +describe('Service Tests', () => { + describe('Logs Service', () => { + let service: JhiConfigurationService; + let httpMock; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule] + }); + + service = TestBed.get(JhiConfigurationService); + httpMock = TestBed.get(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + }); + + describe('Service methods', () => { + it('should call correct URL', () => { + service.get().subscribe(() => {}); + + const req = httpMock.expectOne({ method: 'GET' }); + const resourceUrl = SERVER_API_URL + 'management/configprops'; + expect(req.request.url).toEqual(resourceUrl); + }); + + it('should get the config', () => { + const angularConfig = { + contexts: { + angular: { + beans: ['test2'] + } + } + }; + service.get().subscribe(received => { + expect(received.body[0]).toEqual(angularConfig); + }); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush(angularConfig); + }); + + it('should get the env', () => { + const propertySources = new HttpResponse({ + body: [{ name: 'test1', properties: 'test1' }, { name: 'test2', properties: 'test2' }] + }); + service.get().subscribe(received => { + expect(received.body[0]).toEqual(propertySources); + }); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush(propertySources); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/health/health.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/health/health.component.spec.ts new file mode 100644 index 0000000000..549b430f67 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/health/health.component.spec.ts @@ -0,0 +1,321 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { HttpResponse, HttpErrorResponse } from '@angular/common/http'; +import { of, throwError } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { JhiHealthCheckComponent } from 'app/admin/health/health.component'; +import { JhiHealthService } from 'app/admin/health/health.service'; + +describe('Component Tests', () => { + describe('JhiHealthCheckComponent', () => { + let comp: JhiHealthCheckComponent; + let fixture: ComponentFixture; + let service: JhiHealthService; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [JhiHealthCheckComponent] + }) + .overrideTemplate(JhiHealthCheckComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(JhiHealthCheckComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(JhiHealthService); + }); + + describe('baseName and subSystemName', () => { + it('should return the basename when it has no sub system', () => { + expect(comp.baseName('base')).toBe('base'); + }); + + it('should return the basename when it has sub systems', () => { + expect(comp.baseName('base.subsystem.system')).toBe('base'); + }); + + it('should return the sub system name', () => { + expect(comp.subSystemName('subsystem')).toBe(''); + }); + + it('should return the subsystem when it has multiple keys', () => { + expect(comp.subSystemName('subsystem.subsystem.system')).toBe(' - subsystem.system'); + }); + }); + + describe('transformHealthData', () => { + it('should flatten empty health data', () => { + const data = {}; + const expected = []; + expect(service.transformHealthData(data)).toEqual(expected); + }); + + it('should flatten health data with no subsystems', () => { + const data = { + details: { + status: 'UP', + db: { + status: 'UP', + database: 'H2', + hello: '1' + }, + mail: { + status: 'UP', + error: 'mail.a.b.c' + } + } + }; + const expected = [ + { + name: 'db', + status: 'UP', + details: { + database: 'H2', + hello: '1' + } + }, + { + name: 'mail', + error: 'mail.a.b.c', + status: 'UP' + } + ]; + expect(service.transformHealthData(data)).toEqual(expected); + }); + + it('should flatten health data with subsystems at level 1, main system has no additional information', () => { + const data = { + details: { + status: 'UP', + db: { + status: 'UP', + database: 'H2', + hello: '1' + }, + mail: { + status: 'UP', + error: 'mail.a.b.c' + }, + system: { + status: 'DOWN', + subsystem1: { + status: 'UP', + property1: 'system.subsystem1.property1' + }, + subsystem2: { + status: 'DOWN', + error: 'system.subsystem1.error', + property2: 'system.subsystem2.property2' + } + } + } + }; + const expected = [ + { + name: 'db', + status: 'UP', + details: { + database: 'H2', + hello: '1' + } + }, + { + name: 'mail', + error: 'mail.a.b.c', + status: 'UP' + }, + { + name: 'system.subsystem1', + status: 'UP', + details: { + property1: 'system.subsystem1.property1' + } + }, + { + name: 'system.subsystem2', + error: 'system.subsystem1.error', + status: 'DOWN', + details: { + property2: 'system.subsystem2.property2' + } + } + ]; + expect(service.transformHealthData(data)).toEqual(expected); + }); + + it('should flatten health data with subsystems at level 1, main system has additional information', () => { + const data = { + details: { + status: 'UP', + db: { + status: 'UP', + database: 'H2', + hello: '1' + }, + mail: { + status: 'UP', + error: 'mail.a.b.c' + }, + system: { + status: 'DOWN', + property1: 'system.property1', + subsystem1: { + status: 'UP', + property1: 'system.subsystem1.property1' + }, + subsystem2: { + status: 'DOWN', + error: 'system.subsystem1.error', + property2: 'system.subsystem2.property2' + } + } + } + }; + const expected = [ + { + name: 'db', + status: 'UP', + details: { + database: 'H2', + hello: '1' + } + }, + { + name: 'mail', + error: 'mail.a.b.c', + status: 'UP' + }, + { + name: 'system', + status: 'DOWN', + details: { + property1: 'system.property1' + } + }, + { + name: 'system.subsystem1', + status: 'UP', + details: { + property1: 'system.subsystem1.property1' + } + }, + { + name: 'system.subsystem2', + error: 'system.subsystem1.error', + status: 'DOWN', + details: { + property2: 'system.subsystem2.property2' + } + } + ]; + expect(service.transformHealthData(data)).toEqual(expected); + }); + + it('should flatten health data with subsystems at level 1, main system has additional error', () => { + const data = { + details: { + status: 'UP', + db: { + status: 'UP', + database: 'H2', + hello: '1' + }, + mail: { + status: 'UP', + error: 'mail.a.b.c' + }, + system: { + status: 'DOWN', + error: 'show me', + subsystem1: { + status: 'UP', + property1: 'system.subsystem1.property1' + }, + subsystem2: { + status: 'DOWN', + error: 'system.subsystem1.error', + property2: 'system.subsystem2.property2' + } + } + } + }; + const expected = [ + { + name: 'db', + status: 'UP', + details: { + database: 'H2', + hello: '1' + } + }, + { + name: 'mail', + error: 'mail.a.b.c', + status: 'UP' + }, + { + name: 'system', + error: 'show me', + status: 'DOWN' + }, + { + name: 'system.subsystem1', + status: 'UP', + details: { + property1: 'system.subsystem1.property1' + } + }, + { + name: 'system.subsystem2', + error: 'system.subsystem1.error', + status: 'DOWN', + details: { + property2: 'system.subsystem2.property2' + } + } + ]; + expect(service.transformHealthData(data)).toEqual(expected); + }); + }); + + describe('getBadgeClass', () => { + it('should get badge class', () => { + const upBadgeClass = comp.getBadgeClass('UP'); + const downBadgeClass = comp.getBadgeClass('DOWN'); + expect(upBadgeClass).toEqual('badge-success'); + expect(downBadgeClass).toEqual('badge-danger'); + }); + }); + + describe('refresh', () => { + it('should call refresh on init', () => { + // GIVEN + spyOn(service, 'checkHealth').and.returnValue(of(new HttpResponse())); + spyOn(service, 'transformHealthData').and.returnValue(of({ data: 'test' })); + + // WHEN + comp.ngOnInit(); + + // THEN + expect(service.checkHealth).toHaveBeenCalled(); + expect(service.transformHealthData).toHaveBeenCalled(); + expect(comp.healthData.value).toEqual({ data: 'test' }); + }); + it('should handle a 503 on refreshing health data', () => { + // GIVEN + spyOn(service, 'checkHealth').and.returnValue(throwError(new HttpErrorResponse({ status: 503, error: 'Mail down' }))); + spyOn(service, 'transformHealthData').and.returnValue(of({ health: 'down' })); + + // WHEN + comp.refresh(); + + // THEN + expect(service.checkHealth).toHaveBeenCalled(); + expect(service.transformHealthData).toHaveBeenCalled(); + expect(comp.healthData.value).toEqual({ health: 'down' }); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/logs/logs.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/logs/logs.component.spec.ts new file mode 100644 index 0000000000..def356c0f2 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/logs/logs.component.spec.ts @@ -0,0 +1,77 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { of } from 'rxjs'; +import { HttpHeaders, HttpResponse } from '@angular/common/http'; + +import { BookstoreTestModule } from '../../../test.module'; +import { LogsComponent } from 'app/admin/logs/logs.component'; +import { LogsService } from 'app/admin/logs/logs.service'; +import { ITEMS_PER_PAGE } from 'app/shared'; +import { Log } from 'app/admin'; + +describe('Component Tests', () => { + describe('LogsComponent', () => { + let comp: LogsComponent; + let fixture: ComponentFixture; + let service: LogsService; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [LogsComponent], + providers: [LogsService] + }) + .overrideTemplate(LogsComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(LogsComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(LogsService); + }); + + describe('OnInit', () => { + it('should set all default values correctly', () => { + expect(comp.filter).toBe(''); + expect(comp.orderProp).toBe('name'); + expect(comp.reverse).toBe(false); + }); + it('Should call load all on init', () => { + // GIVEN + const headers = new HttpHeaders().append('link', 'link;link'); + const log = new Log('main', 'WARN'); + spyOn(service, 'findAll').and.returnValue( + of( + new HttpResponse({ + body: [log], + headers + }) + ) + ); + + // WHEN + comp.ngOnInit(); + + // THEN + expect(service.findAll).toHaveBeenCalled(); + expect(comp.loggers[0]).toEqual(jasmine.objectContaining(log)); + }); + }); + describe('change log level', () => { + it('should change log level correctly', () => { + // GIVEN + const log = new Log('main', 'ERROR'); + spyOn(service, 'changeLevel').and.returnValue(of(new HttpResponse())); + spyOn(service, 'findAll').and.returnValue(of(new HttpResponse({ body: [log] }))); + + // WHEN + comp.changeLevel('main', 'ERROR'); + + // THEN + expect(service.changeLevel).toHaveBeenCalled(); + expect(service.findAll).toHaveBeenCalled(); + expect(comp.loggers[0]).toEqual(jasmine.objectContaining(log)); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/logs/logs.service.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/logs/logs.service.spec.ts new file mode 100644 index 0000000000..c34833922e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/logs/logs.service.spec.ts @@ -0,0 +1,58 @@ +import { TestBed } from '@angular/core/testing'; + +import { LogsService } from 'app/admin/logs/logs.service'; +import { Log } from 'app/admin/logs/log.model'; +import { SERVER_API_URL } from 'app/app.constants'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; + +describe('Service Tests', () => { + describe('Logs Service', () => { + let service: LogsService; + let httpMock; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule] + }); + + service = TestBed.get(LogsService); + httpMock = TestBed.get(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + }); + + describe('Service methods', () => { + it('should call correct URL', () => { + service.findAll().subscribe(() => {}); + + const req = httpMock.expectOne({ method: 'GET' }); + const resourceUrl = SERVER_API_URL + 'management/logs'; + expect(req.request.url).toEqual(resourceUrl); + }); + + it('should return Logs', () => { + const log = new Log('main', 'ERROR'); + + service.findAll().subscribe(received => { + expect(received.body[0]).toEqual(log); + }); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush([log]); + }); + + it('should change log level', () => { + const log = new Log('main', 'ERROR'); + + service.changeLevel(log).subscribe(received => { + expect(received.body[0]).toEqual(log); + }); + + const req = httpMock.expectOne({ method: 'PUT' }); + req.flush([log]); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/metrics/metrics.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/metrics/metrics.component.spec.ts new file mode 100644 index 0000000000..d4a992b963 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/metrics/metrics.component.spec.ts @@ -0,0 +1,55 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { HttpResponse, HttpErrorResponse } from '@angular/common/http'; +import { of, throwError } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { JhiMetricsMonitoringComponent } from 'app/admin/metrics/metrics.component'; +import { JhiMetricsService } from 'app/admin/metrics/metrics.service'; + +describe('Component Tests', () => { + describe('JhiMetricsMonitoringComponent', () => { + let comp: JhiMetricsMonitoringComponent; + let fixture: ComponentFixture; + let service: JhiMetricsService; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [JhiMetricsMonitoringComponent] + }) + .overrideTemplate(JhiMetricsMonitoringComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(JhiMetricsMonitoringComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(JhiMetricsService); + }); + + describe('refresh', () => { + it('should call refresh on init', () => { + // GIVEN + const response = { + timers: { + service: 'test', + unrelatedKey: 'test' + }, + gauges: { + 'jcache.statistics': { + value: 2 + }, + unrelatedKey: 'test' + } + }; + spyOn(service, 'getMetrics').and.returnValue(of(response)); + + // WHEN + comp.ngOnInit(); + + // THEN + expect(service.getMetrics).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/metrics/metrics.service.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/metrics/metrics.service.spec.ts new file mode 100644 index 0000000000..2c3665b062 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/metrics/metrics.service.spec.ts @@ -0,0 +1,57 @@ +import { TestBed } from '@angular/core/testing'; + +import { JhiMetricsService } from 'app/admin/metrics/metrics.service'; +import { SERVER_API_URL } from 'app/app.constants'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; + +describe('Service Tests', () => { + describe('Logs Service', () => { + let service: JhiMetricsService; + let httpMock; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule] + }); + + service = TestBed.get(JhiMetricsService); + httpMock = TestBed.get(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + }); + + describe('Service methods', () => { + it('should call correct URL', () => { + service.getMetrics().subscribe(() => {}); + + const req = httpMock.expectOne({ method: 'GET' }); + const resourceUrl = SERVER_API_URL + 'management/jhi-metrics'; + expect(req.request.url).toEqual(resourceUrl); + }); + + it('should return Metrics', () => { + const metrics = []; + + service.getMetrics().subscribe(received => { + expect(received.body[0]).toEqual(metrics); + }); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush([metrics]); + }); + + it('should return Thread Dump', () => { + const dump = [{ name: 'test1', threadState: 'RUNNABLE' }]; + + service.threadDump().subscribe(received => { + expect(received.body[0]).toEqual(dump); + }); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush([dump]); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-delete-dialog.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-delete-dialog.component.spec.ts new file mode 100644 index 0000000000..596e1b5609 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-delete-dialog.component.spec.ts @@ -0,0 +1,54 @@ +import { ComponentFixture, TestBed, async, inject, fakeAsync, tick } from '@angular/core/testing'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Observable, of } from 'rxjs'; +import { JhiEventManager } from 'ng-jhipster'; + +import { BookstoreTestModule } from '../../../test.module'; +import { UserMgmtDeleteDialogComponent } from 'app/admin/user-management/user-management-delete-dialog.component'; +import { UserService } from 'app/core'; + +describe('Component Tests', () => { + describe('User Management Delete Component', () => { + let comp: UserMgmtDeleteDialogComponent; + let fixture: ComponentFixture; + let service: UserService; + let mockEventManager: any; + let mockActiveModal: any; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [UserMgmtDeleteDialogComponent] + }) + .overrideTemplate(UserMgmtDeleteDialogComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(UserMgmtDeleteDialogComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(UserService); + mockEventManager = fixture.debugElement.injector.get(JhiEventManager); + mockActiveModal = fixture.debugElement.injector.get(NgbActiveModal); + }); + + describe('confirmDelete', () => { + it('Should call delete service on confirmDelete', inject( + [], + fakeAsync(() => { + // GIVEN + spyOn(service, 'delete').and.returnValue(of({})); + + // WHEN + comp.confirmDelete('user'); + tick(); + + // THEN + expect(service.delete).toHaveBeenCalledWith('user'); + expect(mockActiveModal.dismissSpy).toHaveBeenCalled(); + expect(mockEventManager.broadcastSpy).toHaveBeenCalled(); + }) + )); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-detail.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-detail.component.spec.ts new file mode 100644 index 0000000000..f64b8bb88b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-detail.component.spec.ts @@ -0,0 +1,65 @@ +import { ComponentFixture, TestBed, async } from '@angular/core/testing'; +import { ActivatedRoute } from '@angular/router'; +import { of } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { UserMgmtDetailComponent } from 'app/admin/user-management/user-management-detail.component'; +import { User } from 'app/core'; + +describe('Component Tests', () => { + describe('User Management Detail Component', () => { + let comp: UserMgmtDetailComponent; + let fixture: ComponentFixture; + const route = ({ + data: of({ user: new User(1, 'user', 'first', 'last', 'first@last.com', true, 'en', ['ROLE_USER'], 'admin', null, null, null) }) + } as any) as ActivatedRoute; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [UserMgmtDetailComponent], + providers: [ + { + provide: ActivatedRoute, + useValue: route + } + ] + }) + .overrideTemplate(UserMgmtDetailComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(UserMgmtDetailComponent); + comp = fixture.componentInstance; + }); + + describe('OnInit', () => { + it('Should call load all on init', () => { + // GIVEN + + // WHEN + comp.ngOnInit(); + + // THEN + expect(comp.user).toEqual( + jasmine.objectContaining({ + id: 1, + login: 'user', + firstName: 'first', + lastName: 'last', + email: 'first@last.com', + activated: true, + langKey: 'en', + authorities: ['ROLE_USER'], + createdBy: 'admin', + createdDate: null, + lastModifiedBy: null, + lastModifiedDate: null, + password: null + }) + ); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-update.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-update.component.spec.ts new file mode 100644 index 0000000000..c98694ba82 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management-update.component.spec.ts @@ -0,0 +1,99 @@ +import { ComponentFixture, TestBed, async, inject, fakeAsync, tick } from '@angular/core/testing'; +import { HttpResponse } from '@angular/common/http'; +import { ActivatedRoute } from '@angular/router'; +import { Observable, of } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { UserMgmtUpdateComponent } from 'app/admin/user-management/user-management-update.component'; +import { UserService, User } from 'app/core'; + +describe('Component Tests', () => { + describe('User Management Update Component', () => { + let comp: UserMgmtUpdateComponent; + let fixture: ComponentFixture; + let service: UserService; + const route = ({ + data: of({ user: new User(1, 'user', 'first', 'last', 'first@last.com', true, 'en', ['ROLE_USER'], 'admin', null, null, null) }) + } as any) as ActivatedRoute; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [UserMgmtUpdateComponent], + providers: [ + { + provide: ActivatedRoute, + useValue: route + } + ] + }) + .overrideTemplate(UserMgmtUpdateComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(UserMgmtUpdateComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(UserService); + }); + + describe('OnInit', () => { + it('Should load authorities and language on init', inject( + [], + fakeAsync(() => { + // GIVEN + spyOn(service, 'authorities').and.returnValue(of(['USER'])); + + // WHEN + comp.ngOnInit(); + + // THEN + expect(service.authorities).toHaveBeenCalled(); + expect(comp.authorities).toEqual(['USER']); + }) + )); + }); + + describe('save', () => { + it('Should call update service on save for existing user', inject( + [], + fakeAsync(() => { + // GIVEN + const entity = new User(123); + spyOn(service, 'update').and.returnValue( + of( + new HttpResponse({ + body: entity + }) + ) + ); + comp.user = entity; + // WHEN + comp.save(); + tick(); // simulate async + + // THEN + expect(service.update).toHaveBeenCalledWith(entity); + expect(comp.isSaving).toEqual(false); + }) + )); + + it('Should call create service on save for new user', inject( + [], + fakeAsync(() => { + // GIVEN + const entity = new User(); + spyOn(service, 'create').and.returnValue(of(new HttpResponse({ body: entity }))); + comp.user = entity; + // WHEN + comp.save(); + tick(); // simulate async + + // THEN + expect(service.create).toHaveBeenCalledWith(entity); + expect(comp.isSaving).toEqual(false); + }) + )); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management.component.spec.ts new file mode 100644 index 0000000000..31fea387b8 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/admin/user-management/user-management.component.spec.ts @@ -0,0 +1,85 @@ +import { ComponentFixture, TestBed, async, inject, fakeAsync, tick } from '@angular/core/testing'; +import { Observable, of } from 'rxjs'; +import { HttpHeaders, HttpResponse } from '@angular/common/http'; + +import { BookstoreTestModule } from '../../../test.module'; +import { UserMgmtComponent } from 'app/admin/user-management/user-management.component'; +import { UserService, User } from 'app/core'; + +describe('Component Tests', () => { + describe('User Management Component', () => { + let comp: UserMgmtComponent; + let fixture: ComponentFixture; + let service: UserService; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [UserMgmtComponent] + }) + .overrideTemplate(UserMgmtComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(UserMgmtComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(UserService); + }); + + describe('OnInit', () => { + it('Should call load all on init', inject( + [], + fakeAsync(() => { + // GIVEN + const headers = new HttpHeaders().append('link', 'link;link'); + spyOn(service, 'query').and.returnValue( + of( + new HttpResponse({ + body: [new User(123)], + headers + }) + ) + ); + + // WHEN + comp.ngOnInit(); + tick(); // simulate async + + // THEN + expect(service.query).toHaveBeenCalled(); + expect(comp.users[0]).toEqual(jasmine.objectContaining({ id: 123 })); + }) + )); + }); + + describe('setActive', () => { + it('Should update user and call load all', inject( + [], + fakeAsync(() => { + // GIVEN + const headers = new HttpHeaders().append('link', 'link;link'); + const user = new User(123); + spyOn(service, 'query').and.returnValue( + of( + new HttpResponse({ + body: [user], + headers + }) + ) + ); + spyOn(service, 'update').and.returnValue(of(new HttpResponse({ status: 200 }))); + + // WHEN + comp.setActive(user, true); + tick(); // simulate async + + // THEN + expect(service.update).toHaveBeenCalledWith(user); + expect(service.query).toHaveBeenCalled(); + expect(comp.users[0]).toEqual(jasmine.objectContaining({ id: 123 })); + }) + )); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/core/user/account.service.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/core/user/account.service.spec.ts new file mode 100644 index 0000000000..01ed421f57 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/core/user/account.service.spec.ts @@ -0,0 +1,102 @@ +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; +import { SERVER_API_URL } from 'app/app.constants'; +import { AccountService } from 'app/core'; +import { JhiDateUtils } from 'ng-jhipster'; +import { SessionStorageService } from 'ngx-webstorage'; + +describe('Service Tests', () => { + describe('Account Service', () => { + let service: AccountService; + let httpMock; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [JhiDateUtils, SessionStorageService] + }); + + service = TestBed.get(AccountService); + httpMock = TestBed.get(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + }); + + describe('Service methods', () => { + it('should call /account if user is undefined', () => { + service.identity().then(() => {}); + const req = httpMock.expectOne({ method: 'GET' }); + const resourceUrl = SERVER_API_URL + 'api/account'; + + expect(req.request.url).toEqual(`${resourceUrl}`); + }); + + it('should call /account only once', () => { + service.identity().then(() => service.identity().then(() => {})); + const req = httpMock.expectOne({ method: 'GET' }); + const resourceUrl = SERVER_API_URL + 'api/account'; + + expect(req.request.url).toEqual(`${resourceUrl}`); + req.flush({ + firstName: 'John' + }); + }); + + describe('hasAuthority', () => { + it('should return false if user is not logged', async () => { + const hasAuthority = await service.hasAuthority('ROLE_USER'); + expect(hasAuthority).toBeFalsy(); + }); + + it('should return false if user is logged and has not authority', async () => { + service.authenticate({ + authorities: ['ROLE_USER'] + }); + + const hasAuthority = await service.hasAuthority('ROLE_ADMIN'); + + expect(hasAuthority).toBeFalsy(); + }); + + it('should return true if user is logged and has authority', async () => { + service.authenticate({ + authorities: ['ROLE_USER'] + }); + + const hasAuthority = await service.hasAuthority('ROLE_USER'); + + expect(hasAuthority).toBeTruthy(); + }); + }); + + describe('hasAnyAuthority', () => { + it('should return false if user is not logged', async () => { + const hasAuthority = await service.hasAnyAuthority(['ROLE_USER']); + expect(hasAuthority).toBeFalsy(); + }); + + it('should return false if user is logged and has not authority', async () => { + service.authenticate({ + authorities: ['ROLE_USER'] + }); + + const hasAuthority = await service.hasAnyAuthority(['ROLE_ADMIN']); + + expect(hasAuthority).toBeFalsy(); + }); + + it('should return true if user is logged and has authority', async () => { + service.authenticate({ + authorities: ['ROLE_USER'] + }); + + const hasAuthority = await service.hasAnyAuthority(['ROLE_USER', 'ROLE_ADMIN']); + + expect(hasAuthority).toBeTruthy(); + }); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/core/user/user.service.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/core/user/user.service.spec.ts new file mode 100644 index 0000000000..9c05839a57 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/core/user/user.service.spec.ts @@ -0,0 +1,66 @@ +import { TestBed } from '@angular/core/testing'; +import { JhiDateUtils } from 'ng-jhipster'; + +import { UserService, User } from 'app/core'; +import { SERVER_API_URL } from 'app/app.constants'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; + +describe('Service Tests', () => { + describe('User Service', () => { + let service: UserService; + let httpMock; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [JhiDateUtils] + }); + + service = TestBed.get(UserService); + httpMock = TestBed.get(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + }); + + describe('Service methods', () => { + it('should call correct URL', () => { + service.find('user').subscribe(() => {}); + + const req = httpMock.expectOne({ method: 'GET' }); + const resourceUrl = SERVER_API_URL + 'api/users'; + expect(req.request.url).toEqual(`${resourceUrl}/user`); + }); + it('should return User', () => { + service.find('user').subscribe(received => { + expect(received.body.login).toEqual('user'); + }); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush(new User(1, 'user')); + }); + + it('should return Authorities', () => { + service.authorities().subscribe(_authorities => { + expect(_authorities).toEqual(['ROLE_USER', 'ROLE_ADMIN']); + }); + const req = httpMock.expectOne({ method: 'GET' }); + + req.flush(['ROLE_USER', 'ROLE_ADMIN']); + }); + + it('should propagate not found response', () => { + service.find('user').subscribe(null, (_error: any) => { + expect(_error.status).toEqual(404); + }); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush('Invalid request parameters', { + status: 404, + statusText: 'Bad Request' + }); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/shared/alert/alert-error.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/shared/alert/alert-error.component.spec.ts new file mode 100644 index 0000000000..93f344e633 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/shared/alert/alert-error.component.spec.ts @@ -0,0 +1,134 @@ +import { ComponentFixture, TestBed, async, inject, fakeAsync, tick } from '@angular/core/testing'; +import { HttpErrorResponse, HttpHeaders } from '@angular/common/http'; +import { JhiAlertService, JhiEventManager } from 'ng-jhipster'; + +import { BookstoreTestModule } from '../../../test.module'; +import { JhiAlertErrorComponent } from 'app/shared/alert/alert-error.component'; +import { MockAlertService } from '../../../helpers/mock-alert.service'; + +describe('Component Tests', () => { + describe('Alert Error Component', () => { + let comp: JhiAlertErrorComponent; + let fixture: ComponentFixture; + let eventManager: JhiEventManager; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [JhiAlertErrorComponent], + providers: [ + JhiEventManager, + { + provide: JhiAlertService, + useClass: MockAlertService + } + ] + }) + .overrideTemplate(JhiAlertErrorComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(JhiAlertErrorComponent); + comp = fixture.componentInstance; + eventManager = fixture.debugElement.injector.get(JhiEventManager); + }); + + describe('Error Handling', () => { + it('Should display an alert on status 0', () => { + // GIVEN + eventManager.broadcast({ name: 'bookstoreApp.httpError', content: { status: 0 } }); + // THEN + expect(comp.alerts.length).toBe(1); + expect(comp.alerts[0].msg).toBe('Server not reachable'); + }); + it('Should display an alert on status 404', () => { + // GIVEN + eventManager.broadcast({ name: 'bookstoreApp.httpError', content: { status: 404 } }); + // THEN + expect(comp.alerts.length).toBe(1); + expect(comp.alerts[0].msg).toBe('Not found'); + }); + it('Should display an alert on generic error', () => { + // GIVEN + eventManager.broadcast({ name: 'bookstoreApp.httpError', content: { error: { message: 'Error Message' } } }); + eventManager.broadcast({ name: 'bookstoreApp.httpError', content: { error: 'Second Error Message' } }); + // THEN + expect(comp.alerts.length).toBe(2); + expect(comp.alerts[0].msg).toBe('Error Message'); + expect(comp.alerts[1].msg).toBe('Second Error Message'); + }); + it('Should display an alert on status 400 for generic error', () => { + // GIVEN + const response = new HttpErrorResponse({ + url: 'http://localhost:8080/api/foos', + headers: new HttpHeaders(), + status: 400, + statusText: 'Bad Request', + error: { + type: 'https://www.jhipster.tech/problem/constraint-violation', + title: 'Bad Request', + status: 400, + path: '/api/foos', + message: 'error.validation' + } + }); + eventManager.broadcast({ name: 'bookstoreApp.httpError', content: response }); + // THEN + expect(comp.alerts.length).toBe(1); + expect(comp.alerts[0].msg).toBe('error.validation'); + }); + it('Should display an alert on status 400 for generic error without message', () => { + // GIVEN + const response = new HttpErrorResponse({ + url: 'http://localhost:8080/api/foos', + headers: new HttpHeaders(), + status: 400, + error: 'Bad Request' + }); + eventManager.broadcast({ name: 'bookstoreApp.httpError', content: response }); + // THEN + expect(comp.alerts.length).toBe(1); + expect(comp.alerts[0].msg).toBe('Bad Request'); + }); + it('Should display an alert on status 400 for invalid parameters', () => { + // GIVEN + const response = new HttpErrorResponse({ + url: 'http://localhost:8080/api/foos', + headers: new HttpHeaders(), + status: 400, + statusText: 'Bad Request', + error: { + type: 'https://www.jhipster.tech/problem/constraint-violation', + title: 'Method argument not valid', + status: 400, + path: '/api/foos', + message: 'error.validation', + fieldErrors: [{ objectName: 'foo', field: 'minField', message: 'Min' }] + } + }); + eventManager.broadcast({ name: 'bookstoreApp.httpError', content: response }); + // THEN + expect(comp.alerts.length).toBe(1); + expect(comp.alerts[0].msg).toBe('Error on field "MinField"'); + }); + it('Should display an alert on status 400 for error headers', () => { + // GIVEN + const response = new HttpErrorResponse({ + url: 'http://localhost:8080/api/foos', + headers: new HttpHeaders().append('app-error', 'Error Message').append('app-params', 'foo'), + status: 400, + statusText: 'Bad Request', + error: { + status: 400, + message: 'error.validation' + } + }); + eventManager.broadcast({ name: 'bookstoreApp.httpError', content: response }); + // THEN + expect(comp.alerts.length).toBe(1); + expect(comp.alerts[0].msg).toBe('Error Message'); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/shared/login/login.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/shared/login/login.component.spec.ts new file mode 100644 index 0000000000..814af64610 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/shared/login/login.component.spec.ts @@ -0,0 +1,157 @@ +import { ComponentFixture, TestBed, async, inject, fakeAsync, tick } from '@angular/core/testing'; +import { Router } from '@angular/router'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { JhiEventManager } from 'ng-jhipster'; + +import { LoginService } from 'app/core/login/login.service'; +import { JhiLoginModalComponent } from 'app/shared/login/login.component'; +import { StateStorageService } from 'app/core/auth/state-storage.service'; +import { BookstoreTestModule } from '../../../test.module'; +import { MockLoginService } from '../../../helpers/mock-login.service'; +import { MockStateStorageService } from '../../../helpers/mock-state-storage.service'; + +describe('Component Tests', () => { + describe('LoginComponent', () => { + let comp: JhiLoginModalComponent; + let fixture: ComponentFixture; + let mockLoginService: any; + let mockStateStorageService: any; + let mockRouter: any; + let mockEventManager: any; + let mockActiveModal: any; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [JhiLoginModalComponent], + providers: [ + { + provide: LoginService, + useClass: MockLoginService + }, + { + provide: StateStorageService, + useClass: MockStateStorageService + } + ] + }) + .overrideTemplate(JhiLoginModalComponent, '') + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(JhiLoginModalComponent); + comp = fixture.componentInstance; + mockLoginService = fixture.debugElement.injector.get(LoginService); + mockStateStorageService = fixture.debugElement.injector.get(StateStorageService); + mockRouter = fixture.debugElement.injector.get(Router); + mockEventManager = fixture.debugElement.injector.get(JhiEventManager); + mockActiveModal = fixture.debugElement.injector.get(NgbActiveModal); + }); + + it('should authenticate the user upon login when previous state was set', inject( + [], + fakeAsync(() => { + // GIVEN + const credentials = { + username: 'admin', + password: 'admin', + rememberMe: true + }; + comp.username = 'admin'; + comp.password = 'admin'; + comp.rememberMe = true; + comp.credentials = credentials; + mockLoginService.setResponse({}); + mockStateStorageService.setResponse({ redirect: 'dummy' }); + + // WHEN/ + comp.login(); + tick(); // simulate async + + // THEN + expect(comp.authenticationError).toEqual(false); + expect(mockActiveModal.dismissSpy).toHaveBeenCalledWith('login success'); + expect(mockEventManager.broadcastSpy).toHaveBeenCalledTimes(1); + expect(mockLoginService.loginSpy).toHaveBeenCalledWith(credentials); + expect(mockStateStorageService.getUrlSpy).toHaveBeenCalledTimes(1); + expect(mockStateStorageService.storeUrlSpy).toHaveBeenCalledWith(null); + expect(mockRouter.navigateSpy).toHaveBeenCalledWith([{ redirect: 'dummy' }]); + }) + )); + + it('should authenticate the user upon login when previous state was not set', inject( + [], + fakeAsync(() => { + // GIVEN + const credentials = { + username: 'admin', + password: 'admin', + rememberMe: true + }; + comp.username = 'admin'; + comp.password = 'admin'; + comp.rememberMe = true; + comp.credentials = credentials; + mockLoginService.setResponse({}); + mockStateStorageService.setResponse(null); + + // WHEN + comp.login(); + tick(); // simulate async + + // THEN + expect(comp.authenticationError).toEqual(false); + expect(mockActiveModal.dismissSpy).toHaveBeenCalledWith('login success'); + expect(mockEventManager.broadcastSpy).toHaveBeenCalledTimes(1); + expect(mockLoginService.loginSpy).toHaveBeenCalledWith(credentials); + expect(mockStateStorageService.getUrlSpy).toHaveBeenCalledTimes(1); + expect(mockStateStorageService.storeUrlSpy).not.toHaveBeenCalled(); + expect(mockRouter.navigateSpy).not.toHaveBeenCalled(); + }) + )); + + it('should empty the credentials upon cancel', () => { + // GIVEN + const credentials = { + username: 'admin', + password: 'admin', + rememberMe: true + }; + + const expected = { + username: null, + password: null, + rememberMe: true + }; + + comp.credentials = credentials; + + // WHEN + comp.cancel(); + + // THEN + expect(comp.authenticationError).toEqual(false); + expect(comp.credentials).toEqual(expected); + expect(mockActiveModal.dismissSpy).toHaveBeenCalledWith('cancel'); + }); + + it('should redirect user when register', () => { + // WHEN + comp.register(); + + // THEN + expect(mockActiveModal.dismissSpy).toHaveBeenCalledWith('to state register'); + expect(mockRouter.navigateSpy).toHaveBeenCalledWith(['/register']); + }); + + it('should redirect user when request password', () => { + // WHEN + comp.requestResetPassword(); + + // THEN + expect(mockActiveModal.dismissSpy).toHaveBeenCalledWith('to state requestReset'); + expect(mockRouter.navigateSpy).toHaveBeenCalledWith(['/reset', 'request']); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-account.service.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-account.service.ts new file mode 100644 index 0000000000..659bf4d379 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-account.service.ts @@ -0,0 +1,35 @@ +import { SpyObject } from './spyobject'; +import { AccountService } from 'app/core/auth/account.service'; +import Spy = jasmine.Spy; + +export class MockAccountService extends SpyObject { + getSpy: Spy; + saveSpy: Spy; + fakeResponse: any; + identitySpy: Spy; + + constructor() { + super(AccountService); + + this.fakeResponse = null; + this.getSpy = this.spy('get').andReturn(this); + this.saveSpy = this.spy('save').andReturn(this); + this.setIdentitySpy({}); + } + + subscribe(callback: any) { + callback(this.fakeResponse); + } + + setResponse(json: any): void { + this.fakeResponse = json; + } + + setIdentitySpy(json: any): any { + this.identitySpy = this.spy('identity').andReturn(Promise.resolve(json)); + } + + setIdentityResponse(json: any): void { + this.setIdentitySpy(json); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-active-modal.service.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-active-modal.service.ts new file mode 100644 index 0000000000..8bf0cc966f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-active-modal.service.ts @@ -0,0 +1,12 @@ +import { SpyObject } from './spyobject'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import Spy = jasmine.Spy; + +export class MockActiveModal extends SpyObject { + dismissSpy: Spy; + + constructor() { + super(NgbActiveModal); + this.dismissSpy = this.spy('dismiss').andReturn(this); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-alert.service.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-alert.service.ts new file mode 100644 index 0000000000..87f36c71e2 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-alert.service.ts @@ -0,0 +1,11 @@ +import { SpyObject } from './spyobject'; +import { JhiAlertService, JhiAlert } from 'ng-jhipster'; + +export class MockAlertService extends SpyObject { + constructor() { + super(JhiAlertService); + } + addAlert(alertOptions: JhiAlert) { + return alertOptions; + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-event-manager.service.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-event-manager.service.ts new file mode 100644 index 0000000000..a71b5d9314 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-event-manager.service.ts @@ -0,0 +1,12 @@ +import { SpyObject } from './spyobject'; +import { JhiEventManager } from 'ng-jhipster'; +import Spy = jasmine.Spy; + +export class MockEventManager extends SpyObject { + broadcastSpy: Spy; + + constructor() { + super(JhiEventManager); + this.broadcastSpy = this.spy('broadcast').andReturn(this); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-login.service.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-login.service.ts new file mode 100644 index 0000000000..93a8ca575f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-login.service.ts @@ -0,0 +1,29 @@ +import { SpyObject } from './spyobject'; +import { LoginService } from 'app/core/login/login.service'; +import Spy = jasmine.Spy; + +export class MockLoginService extends SpyObject { + loginSpy: Spy; + logoutSpy: Spy; + registerSpy: Spy; + requestResetPasswordSpy: Spy; + cancelSpy: Spy; + + constructor() { + super(LoginService); + + this.setLoginSpy({}); + this.logoutSpy = this.spy('logout').andReturn(this); + this.registerSpy = this.spy('register').andReturn(this); + this.requestResetPasswordSpy = this.spy('requestResetPassword').andReturn(this); + this.cancelSpy = this.spy('cancel').andReturn(this); + } + + setLoginSpy(json: any) { + this.loginSpy = this.spy('login').andReturn(Promise.resolve(json)); + } + + setResponse(json: any): void { + this.setLoginSpy(json); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-route.service.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-route.service.ts new file mode 100644 index 0000000000..3465e05524 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-route.service.ts @@ -0,0 +1,29 @@ +import { ActivatedRoute, Router } from '@angular/router'; +import { SpyObject } from './spyobject'; +import { Observable, of } from 'rxjs'; +import Spy = jasmine.Spy; + +export class MockActivatedRoute extends ActivatedRoute { + constructor(parameters?: any) { + super(); + this.queryParams = of(parameters); + this.params = of(parameters); + this.data = of({ + ...parameters, + pagingParams: { + page: 10, + ascending: false, + predicate: 'id' + } + }); + } +} + +export class MockRouter extends SpyObject { + navigateSpy: Spy; + + constructor() { + super(Router); + this.navigateSpy = this.spy('navigate'); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-state-storage.service.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-state-storage.service.ts new file mode 100644 index 0000000000..1398c7b28b --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/mock-state-storage.service.ts @@ -0,0 +1,22 @@ +import { SpyObject } from './spyobject'; +import { StateStorageService } from 'app/core/auth/state-storage.service'; +import Spy = jasmine.Spy; + +export class MockStateStorageService extends SpyObject { + getUrlSpy: Spy; + storeUrlSpy: Spy; + + constructor() { + super(StateStorageService); + this.setUrlSpy({}); + this.storeUrlSpy = this.spy('storeUrl').andReturn(this); + } + + setUrlSpy(json) { + this.getUrlSpy = this.spy('getUrl').andReturn(json); + } + + setResponse(json: any): void { + this.setUrlSpy(json); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/spyobject.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/spyobject.ts new file mode 100644 index 0000000000..949e067ef5 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/helpers/spyobject.ts @@ -0,0 +1,69 @@ +export interface GuinessCompatibleSpy extends jasmine.Spy { + /** By chaining the spy with and.returnValue, all calls to the function will return a specific + * value. */ + andReturn(val: any): void; + /** By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied + * function. */ + andCallFake(fn: Function): GuinessCompatibleSpy; + /** removes all recorded calls */ + reset(); +} + +export class SpyObject { + static stub(object = null, config = null, overrides = null) { + if (!(object instanceof SpyObject)) { + overrides = config; + config = object; + object = new SpyObject(); + } + + const m = {}; + Object.keys(config).forEach(key => (m[key] = config[key])); + Object.keys(overrides).forEach(key => (m[key] = overrides[key])); + Object.keys(m).forEach(key => { + object.spy(key).andReturn(m[key]); + }); + return object; + } + + constructor(type = null) { + if (type) { + Object.keys(type.prototype).forEach(prop => { + let m = null; + try { + m = type.prototype[prop]; + } catch (e) { + // As we are creating spys for abstract classes, + // these classes might have getters that throw when they are accessed. + // As we are only auto creating spys for methods, this + // should not matter. + } + if (typeof m === 'function') { + this.spy(prop); + } + }); + } + } + + spy(name) { + if (!this[name]) { + this[name] = this._createGuinnessCompatibleSpy(name); + } + return this[name]; + } + + prop(name, value) { + this[name] = value; + } + + /** @internal */ + _createGuinnessCompatibleSpy(name): GuinessCompatibleSpy { + const newSpy: GuinessCompatibleSpy = jasmine.createSpy(name); + newSpy.andCallFake = newSpy.and.callFake; + newSpy.andReturn = newSpy.and.returnValue; + newSpy.reset = newSpy.calls.reset; + // revisit return null here (previously needed for rtts_assert). + newSpy.and.returnValue(null); + return newSpy; + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/test.module.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/test.module.ts new file mode 100644 index 0000000000..c66241f9bb --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/test.module.ts @@ -0,0 +1,63 @@ +import { DatePipe } from '@angular/common'; +import { ActivatedRoute, Router } from '@angular/router'; +import { NgModule, ElementRef, Renderer } from '@angular/core'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { JhiDataUtils, JhiDateUtils, JhiEventManager, JhiAlertService, JhiParseLinks } from 'ng-jhipster'; + +import { AccountService, LoginModalService } from 'app/core'; +import { MockAccountService } from './helpers/mock-account.service'; +import { MockActivatedRoute, MockRouter } from './helpers/mock-route.service'; +import { MockActiveModal } from './helpers/mock-active-modal.service'; +import { MockEventManager } from './helpers/mock-event-manager.service'; + +@NgModule({ + providers: [ + DatePipe, + JhiDataUtils, + JhiDateUtils, + JhiParseLinks, + { + provide: JhiEventManager, + useClass: MockEventManager + }, + { + provide: NgbActiveModal, + useClass: MockActiveModal + }, + { + provide: ActivatedRoute, + useValue: new MockActivatedRoute({ id: 123 }) + }, + { + provide: Router, + useClass: MockRouter + }, + { + provide: AccountService, + useClass: MockAccountService + }, + { + provide: LoginModalService, + useValue: null + }, + { + provide: ElementRef, + useValue: null + }, + { + provide: Renderer, + useValue: null + }, + { + provide: JhiAlertService, + useValue: null + }, + { + provide: NgbModal, + useValue: null + } + ], + imports: [HttpClientTestingModule] +}) +export class BookstoreTestModule {} diff --git a/jhipster-5/bookstore-monolith/src/test/resources/config/application.yml b/jhipster-5/bookstore-monolith/src/test/resources/config/application.yml new file mode 100644 index 0000000000..34c6ca3e15 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/resources/config/application.yml @@ -0,0 +1,105 @@ +# =================================================================== +# Spring Boot configuration. +# +# This configuration is used for unit/integration tests. +# +# More information on profiles: https://www.jhipster.tech/profiles/ +# More information on configuration properties: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +# =================================================================== +# Standard Spring Boot properties. +# Full reference is available at: +# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html +# =================================================================== + + +spring: + application: + name: Bookstore + datasource: + type: com.zaxxer.hikari.HikariDataSource + url: jdbc:h2:mem:Bookstore;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + name: + username: + password: + hikari: + auto-commit: false + jpa: + database-platform: io.github.jhipster.domain.util.FixedH2Dialect + database: H2 + open-in-view: false + show-sql: false + hibernate: + ddl-auto: none + naming: + physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy + implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy + properties: + hibernate.id.new_generator_mappings: true + hibernate.connection.provider_disables_autocommit: true + hibernate.cache.use_second_level_cache: false + hibernate.cache.use_query_cache: false + hibernate.generate_statistics: false + hibernate.hbm2ddl.auto: validate + hibernate.jdbc.time_zone: UTC + liquibase: + contexts: test + mail: + host: localhost + messages: + basename: i18n/messages + mvc: + favicon: + enabled: false + thymeleaf: + mode: HTML + + +server: + port: 10344 + address: localhost + +# =================================================================== +# JHipster specific properties +# +# Full reference is available at: https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +jhipster: + async: + core-pool-size: 1 + max-pool-size: 50 + queue-capacity: 10000 + # To test logstash appender + logging: + logstash: + enabled: true + host: localhost + port: 5000 + queue-size: 512 + mail: + from: test@localhost + base-url: http://127.0.0.1:8080 + security: + authentication: + jwt: + # This token must be encoded using Base64 (you can type `echo 'secret-key'|base64` on your command line) + base64-secret: NDJmOTVlZjI2NzhlZDRjNmVkNTM1NDE2NjkyNDljZDJiNzBlMjI5YmZjMjY3MzdjZmZlMjI3NjE4OTRkNzc5MWYzNDNlYWMzYmJjOWRmMjc5ZWQyZTZmOWZkOTMxZWZhNWE1MTVmM2U2NjFmYjhlNDc2Y2Q3NzliMGY0YzFkNmI= + # Token is valid 24 hours + token-validity-in-seconds: 86400 + metrics: + logs: # Reports metrics in the logs + enabled: true + report-frequency: 60 # in seconds + +# =================================================================== +# Application specific properties +# Add your own application properties here, see the ApplicationProperties class +# to have type-safe configuration, like in the JHipsterProperties above +# +# More documentation is available at: +# https://www.jhipster.tech/common-application-properties/ +# =================================================================== + +# application: diff --git a/jhipster-5/bookstore-monolith/src/test/resources/i18n/messages_en.properties b/jhipster-5/bookstore-monolith/src/test/resources/i18n/messages_en.properties new file mode 100644 index 0000000000..f19db8692f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/resources/i18n/messages_en.properties @@ -0,0 +1 @@ +email.test.title=test title diff --git a/jhipster-5/bookstore-monolith/src/test/resources/logback.xml b/jhipster-5/bookstore-monolith/src/test/resources/logback.xml new file mode 100644 index 0000000000..6244807dfa --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/resources/logback.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jhipster-5/bookstore-monolith/src/test/resources/templates/mail/testEmail.html b/jhipster-5/bookstore-monolith/src/test/resources/templates/mail/testEmail.html new file mode 100644 index 0000000000..a4ca16a79f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/resources/templates/mail/testEmail.html @@ -0,0 +1 @@ + diff --git a/jhipster-5/bookstore-monolith/tsconfig-aot.json b/jhipster-5/bookstore-monolith/tsconfig-aot.json new file mode 100644 index 0000000000..110cde9fd6 --- /dev/null +++ b/jhipster-5/bookstore-monolith/tsconfig-aot.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "es2015", + "moduleResolution": "node", + "sourceMap": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": false, + "suppressImplicitAnyIndexErrors": true, + "skipLibCheck": true, + "outDir": "target/www/app", + "lib": ["es7", "dom"], + "typeRoots": ["node_modules/@types"], + "baseUrl": "./", + "paths": { + "app/*": ["src/main/webapp/app/*"] + }, + "importHelpers": true + }, + "angularCompilerOptions": { + "genDir": "target/aot", + "skipMetadataEmit": true, + "fullTemplateTypeCheck": true, + "preserveWhitespaces": true + } +} diff --git a/jhipster-5/bookstore-monolith/tsconfig.json b/jhipster-5/bookstore-monolith/tsconfig.json new file mode 100644 index 0000000000..dd6343ab62 --- /dev/null +++ b/jhipster-5/bookstore-monolith/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": false, + "skipLibCheck": true, + "suppressImplicitAnyIndexErrors": true, + "outDir": "target/www/app", + "lib": ["es7", "dom"], + "typeRoots": ["node_modules/@types"], + "baseUrl": "./", + "paths": { + "app/*": ["src/main/webapp/app/*"] + }, + "importHelpers": true, + "allowJs": true + }, + "include": ["src/main/webapp/app", "src/test/javascript/"], + "exclude": ["node_modules"] +} diff --git a/jhipster-5/bookstore-monolith/tslint.json b/jhipster-5/bookstore-monolith/tslint.json new file mode 100644 index 0000000000..3b8456d2fd --- /dev/null +++ b/jhipster-5/bookstore-monolith/tslint.json @@ -0,0 +1,76 @@ +{ + "rulesDirectory": ["node_modules/codelyzer"], + "extends": ["tslint-config-prettier"], + "rules": { + "class-name": true, + "comment-format": [true, "check-space"], + "curly": true, + "eofline": true, + "forin": true, + "indent": [true, "spaces"], + "label-position": true, + "member-access": false, + "member-ordering": [true, "static-before-instance", "variables-before-functions"], + "no-arg": true, + "no-bitwise": true, + "no-console": [true, "debug", "info", "time", "timeEnd", "trace"], + "no-construct": true, + "no-debugger": true, + "no-duplicate-variable": true, + "no-empty": false, + "no-eval": true, + "no-inferrable-types": [true], + "no-shadowed-variable": true, + "no-string-literal": false, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unused-expression": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [true, "check-open-brace", "check-catch", "check-else", "check-whitespace"], + "quotemark": [true, "single", "avoid-escape"], + "radix": true, + "semicolon": [true, "always", "ignore-bound-class-methods"], + "triple-equals": [true, "allow-null-check"], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "variable-name": false, + "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-separator", "check-type"], + "prefer-const": true, + "arrow-parens": [true, "ban-single-arg-parens"], + "arrow-return-shorthand": [true], + "import-spacing": true, + "no-consecutive-blank-lines": [true], + "object-literal-shorthand": true, + "space-before-function-paren": [ + true, + { + "asyncArrow": "always", + "anonymous": "never", + "constructor": "never", + "method": "never", + "named": "never" + } + ], + + "directive-selector": [true, "attribute", "jhi", "camelCase"], + "component-selector": [true, "element", "jhi", "kebab-case"], + "use-input-property-decorator": true, + "use-output-property-decorator": true, + "use-host-property-decorator": true, + "no-input-rename": true, + "no-output-rename": true, + "use-life-cycle-interface": true, + "use-pipe-transform-interface": false, + "component-class-suffix": true, + "directive-class-suffix": true + } +} diff --git a/jhipster-5/bookstore-monolith/webpack/logo-jhipster.png b/jhipster-5/bookstore-monolith/webpack/logo-jhipster.png new file mode 100644 index 0000000000000000000000000000000000000000..d8eb48da05c157571eed9fd7303f8d9566f2ea12 GIT binary patch literal 4459 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 { + if (err) { + throw new Error('Failed to parse pom.xml: ' + err); + } + if (result.project.version && result.project.version[0]) { + version = result.project.version[0]; + } else if (result.project.parent && result.project.parent[0] && result.project.parent[0].version && result.project.parent[0].version[0]) { + version = result.project.parent[0].version[0]; + } + }); + if (version === null) { + throw new Error('pom.xml is malformed. No version is defined'); + } + return version; +} + +const _root = path.resolve(__dirname, '..'); + +function root(args) { + args = Array.prototype.slice.call(arguments, 0); + return path.join.apply(path, [_root].concat(args)); +} + +function isExternalLib(module, check = /node_modules/) { + const req = module.userRequest; + if (typeof req !== 'string') { + return false; + } + return req.search(check) >= 0; +} diff --git a/jhipster-5/bookstore-monolith/webpack/webpack.common.js b/jhipster-5/bookstore-monolith/webpack/webpack.common.js new file mode 100644 index 0000000000..d8fd26c157 --- /dev/null +++ b/jhipster-5/bookstore-monolith/webpack/webpack.common.js @@ -0,0 +1,86 @@ +const webpack = require('webpack'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const rxPaths = require('rxjs/_esm5/path-mapping'); + +const utils = require('./utils.js'); + +module.exports = (options) => ({ + resolve: { + extensions: ['.ts', '.js'], + modules: ['node_modules'], + alias: { + app: utils.root('src/main/webapp/app/'), + ...rxPaths() + } + }, + stats: { + children: false + }, + module: { + rules: [ + { + test: /\.html$/, + loader: 'html-loader', + options: { + minimize: true, + caseSensitive: true, + removeAttributeQuotes:false, + minifyJS:false, + minifyCSS:false + }, + exclude: /(src\/main\/webapp\/index.html)/ + }, + { + test: /\.(jpe?g|png|gif|svg|woff2?|ttf|eot)$/i, + loader: 'file-loader', + options: { + digest: 'hex', + hash: 'sha512', + name: 'content/[hash].[ext]' + } + }, + { + test: /manifest.webapp$/, + loader: 'file-loader', + options: { + name: 'manifest.webapp' + } + }, + // Ignore warnings about System.import in Angular + { test: /[\/\\]@angular[\/\\].+\.js$/, parser: { system: true } }, + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: `'${options.env}'`, + BUILD_TIMESTAMP: `'${new Date().getTime()}'`, + VERSION: `'${utils.parseVersion()}'`, + DEBUG_INFO_ENABLED: options.env === 'development', + // The root URL for API calls, ending with a '/' - for example: `"https://www.jhipster.tech:8081/myservice/"`. + // If this URL is left empty (""), then it will be relative to the current context. + // If you use an API server, in `prod` mode, you will need to enable CORS + // (see the `jhipster.cors` common JHipster property in the `application-*.yml` configurations) + SERVER_API_URL: `''` + } + }), + new CopyWebpackPlugin([ + { from: './node_modules/swagger-ui/dist/css', to: 'swagger-ui/dist/css' }, + { from: './node_modules/swagger-ui/dist/lib', to: 'swagger-ui/dist/lib' }, + { from: './node_modules/swagger-ui/dist/swagger-ui.min.js', to: 'swagger-ui/dist/swagger-ui.min.js' }, + { from: './src/main/webapp/swagger-ui/', to: 'swagger-ui' }, + { from: './src/main/webapp/content/', to: 'content' }, + { from: './src/main/webapp/favicon.ico', to: 'favicon.ico' }, + { from: './src/main/webapp/manifest.webapp', to: 'manifest.webapp' }, + // jhipster-needle-add-assets-to-webpack - JHipster will add/remove third-party resources in this array + { from: './src/main/webapp/robots.txt', to: 'robots.txt' } + ]), + new HtmlWebpackPlugin({ + template: './src/main/webapp/index.html', + chunks: ['vendors', 'polyfills', 'main', 'global'], + chunksSortMode: 'manual', + inject: 'body' + }) + ] +}); diff --git a/jhipster-5/bookstore-monolith/webpack/webpack.dev.js b/jhipster-5/bookstore-monolith/webpack/webpack.dev.js new file mode 100644 index 0000000000..d05a7ddea8 --- /dev/null +++ b/jhipster-5/bookstore-monolith/webpack/webpack.dev.js @@ -0,0 +1,148 @@ +const webpack = require('webpack'); +const writeFilePlugin = require('write-file-webpack-plugin'); +const webpackMerge = require('webpack-merge'); +const BrowserSyncPlugin = require('browser-sync-webpack-plugin'); +const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); +const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); +const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin'); +const WebpackNotifierPlugin = require('webpack-notifier'); +const path = require('path'); +const sass = require('sass'); + +const utils = require('./utils.js'); +const commonConfig = require('./webpack.common.js'); + +const ENV = 'development'; + +module.exports = (options) => webpackMerge(commonConfig({ env: ENV }), { + devtool: 'eval-source-map', + devServer: { + contentBase: './target/www', + proxy: [{ + context: [ + /* jhipster-needle-add-entity-to-webpack - JHipster will add entity api paths here */ + '/api', + '/management', + '/swagger-resources', + '/v2/api-docs', + '/h2-console', + '/auth' + ], + target: `http${options.tls ? 's' : ''}://127.0.0.1:8080`, + secure: false, + changeOrigin: options.tls, + headers: { host: 'localhost:9000' } + }], + stats: options.stats, + watchOptions: { + ignored: /node_modules/ + } + }, + entry: { + polyfills: './src/main/webapp/app/polyfills', + global: './src/main/webapp/content/scss/global.scss', + main: './src/main/webapp/app/app.main' + }, + output: { + path: utils.root('target/www'), + filename: 'app/[name].bundle.js', + chunkFilename: 'app/[id].chunk.js' + }, + module: { + rules: [{ + test: /\.ts$/, + enforce: 'pre', + loader: 'tslint-loader', + exclude: [/(node_modules)/, new RegExp('reflect-metadata\\' + path.sep + 'Reflect\\.ts')] + }, + { + test: /\.ts$/, + use: [ + 'angular2-template-loader', + { + loader: 'cache-loader', + options: { + cacheDirectory: path.resolve('target/cache-loader') + } + }, + { + loader: 'thread-loader', + options: { + // there should be 1 cpu for the fork-ts-checker-webpack-plugin + workers: require('os').cpus().length - 1 + } + }, + { + loader: 'ts-loader', + options: { + transpileOnly: true, + happyPackMode: true + } + }, + 'angular-router-loader' + ], + exclude: /(node_modules)/ + }, + { + test: /\.scss$/, + use: ['to-string-loader', 'css-loader', { + loader: 'sass-loader', + options: { implementation: sass } + }], + exclude: /(vendor\.scss|global\.scss)/ + }, + { + test: /(vendor\.scss|global\.scss)/, + use: ['style-loader', 'css-loader', 'postcss-loader', { + loader: 'sass-loader', + options: { implementation: sass } + }] + }, + { + test: /\.css$/, + use: ['to-string-loader', 'css-loader'], + exclude: /(vendor\.css|global\.css)/ + }, + { + test: /(vendor\.css|global\.css)/, + use: ['style-loader', 'css-loader'] + }] + }, + stats: process.env.JHI_DISABLE_WEBPACK_LOGS ? 'none' : options.stats, + plugins: [ + process.env.JHI_DISABLE_WEBPACK_LOGS + ? null + : new SimpleProgressWebpackPlugin({ + format: options.stats === 'minimal' ? 'compact' : 'expanded' + }), + new FriendlyErrorsWebpackPlugin(), + new ForkTsCheckerWebpackPlugin(), + new BrowserSyncPlugin({ + host: 'localhost', + port: 9000, + proxy: { + target: 'http://localhost:9060' + }, + socket: { + clients: { + heartbeatTimeout: 60000 + } + } + }, { + reload: false + }), + new webpack.ContextReplacementPlugin( + /angular(\\|\/)core(\\|\/)/, + path.resolve(__dirname, './src/main/webapp') + ), + new writeFilePlugin(), + new webpack.WatchIgnorePlugin([ + utils.root('src/test'), + ]), + new WebpackNotifierPlugin({ + title: 'JHipster', + contentImage: path.join(__dirname, 'logo-jhipster.png') + }) + ].filter(Boolean), + mode: 'development' +}); diff --git a/jhipster-5/bookstore-monolith/webpack/webpack.prod.js b/jhipster-5/bookstore-monolith/webpack/webpack.prod.js new file mode 100644 index 0000000000..ebafa2f631 --- /dev/null +++ b/jhipster-5/bookstore-monolith/webpack/webpack.prod.js @@ -0,0 +1,144 @@ +const webpack = require('webpack'); +const webpackMerge = require('webpack-merge'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const Visualizer = require('webpack-visualizer-plugin'); +const MomentLocalesPlugin = require('moment-locales-webpack-plugin'); +const TerserPlugin = require('terser-webpack-plugin'); +const WorkboxPlugin = require('workbox-webpack-plugin'); +const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin; +const path = require('path'); + +const utils = require('./utils.js'); +const commonConfig = require('./webpack.common.js'); + +const ENV = 'production'; +const sass = require('sass'); + +module.exports = webpackMerge(commonConfig({ env: ENV }), { + // Enable source maps. Please note that this will slow down the build. + // You have to enable it in UglifyJSPlugin config below and in tsconfig-aot.json as well + // devtool: 'source-map', + entry: { + polyfills: './src/main/webapp/app/polyfills', + global: './src/main/webapp/content/scss/global.scss', + main: './src/main/webapp/app/app.main' + }, + output: { + path: utils.root('target/www'), + filename: 'app/[name].[hash].bundle.js', + chunkFilename: 'app/[id].[hash].chunk.js' + }, + module: { + rules: [{ + test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, + loader: '@ngtools/webpack' + }, + { + test: /\.scss$/, + use: ['to-string-loader', 'css-loader', { + loader: 'sass-loader', + options: { implementation: sass } + }], + exclude: /(vendor\.scss|global\.scss)/ + }, + { + test: /(vendor\.scss|global\.scss)/, + use: [ + MiniCssExtractPlugin.loader, + 'css-loader', + 'postcss-loader', + { + loader: 'sass-loader', + options: { implementation: sass } + } + ] + }, + { + test: /\.css$/, + use: ['to-string-loader', 'css-loader'], + exclude: /(vendor\.css|global\.css)/ + }, + { + test: /(vendor\.css|global\.css)/, + use: [ + MiniCssExtractPlugin.loader, + 'css-loader', + 'postcss-loader' + ] + }] + }, + optimization: { + runtimeChunk: false, + splitChunks: { + cacheGroups: { + commons: { + test: /[\\/]node_modules[\\/]/, + name: 'vendors', + chunks: 'all' + } + } + }, + minimizer: [ + new TerserPlugin({ + parallel: true, + cache: true, + terserOptions: { + ie8: false, + // sourceMap: true, // Enable source maps. Please note that this will slow down the build + compress: { + dead_code: true, + warnings: false, + properties: true, + drop_debugger: true, + conditionals: true, + booleans: true, + loops: true, + unused: true, + toplevel: true, + if_return: true, + inline: true, + join_vars: true + }, + output: { + comments: false, + beautify: false, + indent_level: 2 + } + } + }), + new OptimizeCSSAssetsPlugin({}) + ] + }, + plugins: [ + new MiniCssExtractPlugin({ + // Options similar to the same options in webpackOptions.output + // both options are optional + filename: '[name].[contenthash].css', + chunkFilename: '[id].css' + }), + new MomentLocalesPlugin({ + localesToKeep: [ + // jhipster-needle-i18n-language-moment-webpack - JHipster will add/remove languages in this array + ] + }), + new Visualizer({ + // Webpack statistics in target folder + filename: '../stats.html' + }), + new AngularCompilerPlugin({ + mainPath: utils.root('src/main/webapp/app/app.main.ts'), + tsConfigPath: utils.root('tsconfig-aot.json'), + sourceMap: true + }), + new webpack.LoaderOptionsPlugin({ + minimize: true, + debug: false + }), + new WorkboxPlugin.GenerateSW({ + clientsClaim: true, + skipWaiting: true, + }) + ], + mode: 'production' +}); From 57ae9db85485c3ac92025c451f3486e7b6a58e4c Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 19 Mar 2019 06:42:25 -0600 Subject: [PATCH 415/496] Add book entity to jhipster-5 project --- .../bookstore-monolith/.jhipster/Book.json | 54 +++ .../com/baeldung/jhipster5/domain/Book.java | 153 +++++++ .../jhipster5/repository/BookRepository.java | 15 + .../jhipster5/service/BookService.java | 43 ++ .../jhipster5/service/dto/BookDTO.java | 112 +++++ .../service/impl/BookServiceImpl.java | 90 ++++ .../jhipster5/service/mapper/BookMapper.java | 24 + .../service/mapper/EntityMapper.java | 21 + .../jhipster5/web/rest/BookResource.java | 112 +++++ .../20190319124041_added_entity_Book.xml | 50 +++ .../resources/config/liquibase/master.xml | 1 + .../book/book-delete-dialog.component.html | 19 + .../book/book-delete-dialog.component.ts | 65 +++ .../entities/book/book-detail.component.html | 43 ++ .../entities/book/book-detail.component.ts | 24 + .../entities/book/book-update.component.html | 100 +++++ .../entities/book/book-update.component.ts | 53 +++ .../app/entities/book/book.component.html | 62 +++ .../app/entities/book/book.component.ts | 65 +++ .../webapp/app/entities/book/book.module.ts | 23 + .../webapp/app/entities/book/book.route.ts | 93 ++++ .../webapp/app/entities/book/book.service.ts | 74 ++++ .../main/webapp/app/entities/book/index.ts | 6 + .../main/webapp/app/entities/entity.module.ts | 4 + .../app/layouts/navbar/navbar.component.html | 6 + .../webapp/app/shared/model/book.model.ts | 21 + .../web/rest/BookResourceIntTest.java | 416 ++++++++++++++++++ .../book/book-delete-dialog.component.spec.ts | 52 +++ .../book/book-detail.component.spec.ts | 40 ++ .../book/book-update.component.spec.ts | 60 +++ .../app/entities/book/book.component.spec.ts | 51 +++ .../app/entities/book/book.service.spec.ts | 137 ++++++ 32 files changed, 2089 insertions(+) create mode 100644 jhipster-5/bookstore-monolith/.jhipster/Book.json create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/Book.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/BookRepository.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/BookDTO.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/BookMapper.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/EntityMapper.java create mode 100644 jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java create mode 100644 jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/changelog/20190319124041_added_entity_Book.xml create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-delete-dialog.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-delete-dialog.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-update.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-update.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.component.html create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.component.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.module.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.route.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.service.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/index.ts create mode 100644 jhipster-5/bookstore-monolith/src/main/webapp/app/shared/model/book.model.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/BookResourceIntTest.java create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-delete-dialog.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-detail.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-update.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book.component.spec.ts create mode 100644 jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book.service.spec.ts diff --git a/jhipster-5/bookstore-monolith/.jhipster/Book.json b/jhipster-5/bookstore-monolith/.jhipster/Book.json new file mode 100644 index 0000000000..4c5bd1fa52 --- /dev/null +++ b/jhipster-5/bookstore-monolith/.jhipster/Book.json @@ -0,0 +1,54 @@ +{ + "fluentMethods": true, + "clientRootFolder": "", + "relationships": [], + "fields": [ + { + "fieldName": "title", + "fieldType": "String", + "fieldValidateRules": [ + "required" + ] + }, + { + "fieldName": "author", + "fieldType": "String", + "fieldValidateRules": [ + "required" + ] + }, + { + "fieldName": "published", + "fieldType": "LocalDate", + "fieldValidateRules": [ + "required" + ] + }, + { + "fieldName": "quantity", + "fieldType": "Integer", + "fieldValidateRules": [ + "required", + "min" + ], + "fieldValidateRulesMin": 0 + }, + { + "fieldName": "price", + "fieldType": "Double", + "fieldValidateRules": [ + "required", + "min" + ], + "fieldValidateRulesMin": 0 + } + ], + "changelogDate": "20190319124041", + "dto": "mapstruct", + "searchEngine": false, + "service": "serviceImpl", + "entityTableName": "book", + "databaseType": "sql", + "jpaMetamodelFiltering": false, + "pagination": "no" +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/Book.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/Book.java new file mode 100644 index 0000000000..16771d9e09 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/domain/Book.java @@ -0,0 +1,153 @@ +package com.baeldung.jhipster5.domain; + + + +import javax.persistence.*; +import javax.validation.constraints.*; + +import java.io.Serializable; +import java.time.LocalDate; +import java.util.Objects; + +/** + * A Book. + */ +@Entity +@Table(name = "book") +public class Book implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull + @Column(name = "title", nullable = false) + private String title; + + @NotNull + @Column(name = "author", nullable = false) + private String author; + + @NotNull + @Column(name = "published", nullable = false) + private LocalDate published; + + @NotNull + @Min(value = 0) + @Column(name = "quantity", nullable = false) + private Integer quantity; + + @NotNull + @DecimalMin(value = "0") + @Column(name = "price", nullable = false) + private Double price; + + // jhipster-needle-entity-add-field - JHipster will add fields here, do not remove + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public Book title(String title) { + this.title = title; + return this; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public Book author(String author) { + this.author = author; + return this; + } + + public void setAuthor(String author) { + this.author = author; + } + + public LocalDate getPublished() { + return published; + } + + public Book published(LocalDate published) { + this.published = published; + return this; + } + + public void setPublished(LocalDate published) { + this.published = published; + } + + public Integer getQuantity() { + return quantity; + } + + public Book quantity(Integer quantity) { + this.quantity = quantity; + return this; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + public Double getPrice() { + return price; + } + + public Book price(Double price) { + this.price = price; + return this; + } + + public void setPrice(Double price) { + this.price = price; + } + // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Book book = (Book) o; + if (book.getId() == null || getId() == null) { + return false; + } + return Objects.equals(getId(), book.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(getId()); + } + + @Override + public String toString() { + return "Book{" + + "id=" + getId() + + ", title='" + getTitle() + "'" + + ", author='" + getAuthor() + "'" + + ", published='" + getPublished() + "'" + + ", quantity=" + getQuantity() + + ", price=" + getPrice() + + "}"; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/BookRepository.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/BookRepository.java new file mode 100644 index 0000000000..ebd3117e65 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/repository/BookRepository.java @@ -0,0 +1,15 @@ +package com.baeldung.jhipster5.repository; + +import com.baeldung.jhipster5.domain.Book; +import org.springframework.data.jpa.repository.*; +import org.springframework.stereotype.Repository; + + +/** + * Spring Data repository for the Book entity. + */ +@SuppressWarnings("unused") +@Repository +public interface BookRepository extends JpaRepository { + +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java new file mode 100644 index 0000000000..bb052dc03c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java @@ -0,0 +1,43 @@ +package com.baeldung.jhipster5.service; + +import com.baeldung.jhipster5.service.dto.BookDTO; + +import java.util.List; +import java.util.Optional; + +/** + * Service Interface for managing Book. + */ +public interface BookService { + + /** + * Save a book. + * + * @param bookDTO the entity to save + * @return the persisted entity + */ + BookDTO save(BookDTO bookDTO); + + /** + * Get all the books. + * + * @return the list of entities + */ + List findAll(); + + + /** + * Get the "id" book. + * + * @param id the id of the entity + * @return the entity + */ + Optional findOne(Long id); + + /** + * Delete the "id" book. + * + * @param id the id of the entity + */ + void delete(Long id); +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/BookDTO.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/BookDTO.java new file mode 100644 index 0000000000..5aa550e989 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/dto/BookDTO.java @@ -0,0 +1,112 @@ +package com.baeldung.jhipster5.service.dto; +import java.time.LocalDate; +import javax.validation.constraints.*; +import java.io.Serializable; +import java.util.Objects; + +/** + * A DTO for the Book entity. + */ +public class BookDTO implements Serializable { + + private Long id; + + @NotNull + private String title; + + @NotNull + private String author; + + @NotNull + private LocalDate published; + + @NotNull + @Min(value = 0) + private Integer quantity; + + @NotNull + @DecimalMin(value = "0") + private Double price; + + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public LocalDate getPublished() { + return published; + } + + public void setPublished(LocalDate published) { + this.published = published; + } + + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + BookDTO bookDTO = (BookDTO) o; + if (bookDTO.getId() == null || getId() == null) { + return false; + } + return Objects.equals(getId(), bookDTO.getId()); + } + + @Override + public int hashCode() { + return Objects.hashCode(getId()); + } + + @Override + public String toString() { + return "BookDTO{" + + "id=" + getId() + + ", title='" + getTitle() + "'" + + ", author='" + getAuthor() + "'" + + ", published='" + getPublished() + "'" + + ", quantity=" + getQuantity() + + ", price=" + getPrice() + + "}"; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java new file mode 100644 index 0000000000..00f68b84af --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java @@ -0,0 +1,90 @@ +package com.baeldung.jhipster5.service.impl; + +import com.baeldung.jhipster5.service.BookService; +import com.baeldung.jhipster5.domain.Book; +import com.baeldung.jhipster5.repository.BookRepository; +import com.baeldung.jhipster5.service.dto.BookDTO; +import com.baeldung.jhipster5.service.mapper.BookMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Service Implementation for managing Book. + */ +@Service +@Transactional +public class BookServiceImpl implements BookService { + + private final Logger log = LoggerFactory.getLogger(BookServiceImpl.class); + + private final BookRepository bookRepository; + + private final BookMapper bookMapper; + + public BookServiceImpl(BookRepository bookRepository, BookMapper bookMapper) { + this.bookRepository = bookRepository; + this.bookMapper = bookMapper; + } + + /** + * Save a book. + * + * @param bookDTO the entity to save + * @return the persisted entity + */ + @Override + public BookDTO save(BookDTO bookDTO) { + log.debug("Request to save Book : {}", bookDTO); + Book book = bookMapper.toEntity(bookDTO); + book = bookRepository.save(book); + return bookMapper.toDto(book); + } + + /** + * Get all the books. + * + * @return the list of entities + */ + @Override + @Transactional(readOnly = true) + public List findAll() { + log.debug("Request to get all Books"); + return bookRepository.findAll().stream() + .map(bookMapper::toDto) + .collect(Collectors.toCollection(LinkedList::new)); + } + + + /** + * Get one book by id. + * + * @param id the id of the entity + * @return the entity + */ + @Override + @Transactional(readOnly = true) + public Optional findOne(Long id) { + log.debug("Request to get Book : {}", id); + return bookRepository.findById(id) + .map(bookMapper::toDto); + } + + /** + * Delete the book by id. + * + * @param id the id of the entity + */ + @Override + public void delete(Long id) { + log.debug("Request to delete Book : {}", id); + bookRepository.deleteById(id); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/BookMapper.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/BookMapper.java new file mode 100644 index 0000000000..cd24c7088e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/BookMapper.java @@ -0,0 +1,24 @@ +package com.baeldung.jhipster5.service.mapper; + +import com.baeldung.jhipster5.domain.*; +import com.baeldung.jhipster5.service.dto.BookDTO; + +import org.mapstruct.*; + +/** + * Mapper for the entity Book and its DTO BookDTO. + */ +@Mapper(componentModel = "spring", uses = {}) +public interface BookMapper extends EntityMapper { + + + + default Book fromId(Long id) { + if (id == null) { + return null; + } + Book book = new Book(); + book.setId(id); + return book; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/EntityMapper.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/EntityMapper.java new file mode 100644 index 0000000000..68af78179d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/mapper/EntityMapper.java @@ -0,0 +1,21 @@ +package com.baeldung.jhipster5.service.mapper; + +import java.util.List; + +/** + * Contract for a generic dto to entity mapper. + * + * @param - DTO type parameter. + * @param - Entity type parameter. + */ + +public interface EntityMapper { + + E toEntity(D dto); + + D toDto(E entity); + + List toEntity(List dtoList); + + List toDto(List entityList); +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java new file mode 100644 index 0000000000..efcc2c3495 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java @@ -0,0 +1,112 @@ +package com.baeldung.jhipster5.web.rest; +import com.baeldung.jhipster5.service.BookService; +import com.baeldung.jhipster5.web.rest.errors.BadRequestAlertException; +import com.baeldung.jhipster5.web.rest.util.HeaderUtil; +import com.baeldung.jhipster5.service.dto.BookDTO; +import io.github.jhipster.web.util.ResponseUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; +import java.net.URI; +import java.net.URISyntaxException; + +import java.util.List; +import java.util.Optional; + +/** + * REST controller for managing Book. + */ +@RestController +@RequestMapping("/api") +public class BookResource { + + private final Logger log = LoggerFactory.getLogger(BookResource.class); + + private static final String ENTITY_NAME = "book"; + + private final BookService bookService; + + public BookResource(BookService bookService) { + this.bookService = bookService; + } + + /** + * POST /books : Create a new book. + * + * @param bookDTO the bookDTO to create + * @return the ResponseEntity with status 201 (Created) and with body the new bookDTO, or with status 400 (Bad Request) if the book has already an ID + * @throws URISyntaxException if the Location URI syntax is incorrect + */ + @PostMapping("/books") + public ResponseEntity createBook(@Valid @RequestBody BookDTO bookDTO) throws URISyntaxException { + log.debug("REST request to save Book : {}", bookDTO); + if (bookDTO.getId() != null) { + throw new BadRequestAlertException("A new book cannot already have an ID", ENTITY_NAME, "idexists"); + } + BookDTO result = bookService.save(bookDTO); + return ResponseEntity.created(new URI("/api/books/" + result.getId())) + .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString())) + .body(result); + } + + /** + * PUT /books : Updates an existing book. + * + * @param bookDTO the bookDTO to update + * @return the ResponseEntity with status 200 (OK) and with body the updated bookDTO, + * or with status 400 (Bad Request) if the bookDTO is not valid, + * or with status 500 (Internal Server Error) if the bookDTO couldn't be updated + * @throws URISyntaxException if the Location URI syntax is incorrect + */ + @PutMapping("/books") + public ResponseEntity updateBook(@Valid @RequestBody BookDTO bookDTO) throws URISyntaxException { + log.debug("REST request to update Book : {}", bookDTO); + if (bookDTO.getId() == null) { + throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); + } + BookDTO result = bookService.save(bookDTO); + return ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, bookDTO.getId().toString())) + .body(result); + } + + /** + * GET /books : get all the books. + * + * @return the ResponseEntity with status 200 (OK) and the list of books in body + */ + @GetMapping("/books") + public List getAllBooks() { + log.debug("REST request to get all Books"); + return bookService.findAll(); + } + + /** + * GET /books/:id : get the "id" book. + * + * @param id the id of the bookDTO to retrieve + * @return the ResponseEntity with status 200 (OK) and with body the bookDTO, or with status 404 (Not Found) + */ + @GetMapping("/books/{id}") + public ResponseEntity getBook(@PathVariable Long id) { + log.debug("REST request to get Book : {}", id); + Optional bookDTO = bookService.findOne(id); + return ResponseUtil.wrapOrNotFound(bookDTO); + } + + /** + * DELETE /books/:id : delete the "id" book. + * + * @param id the id of the bookDTO to delete + * @return the ResponseEntity with status 200 (OK) + */ + @DeleteMapping("/books/{id}") + public ResponseEntity deleteBook(@PathVariable Long id) { + log.debug("REST request to delete Book : {}", id); + bookService.delete(id); + return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/changelog/20190319124041_added_entity_Book.xml b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/changelog/20190319124041_added_entity_Book.xml new file mode 100644 index 0000000000..f040387cf1 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/changelog/20190319124041_added_entity_Book.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/master.xml b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/master.xml index f2b0b1f7e6..e045ee0100 100644 --- a/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/master.xml +++ b/jhipster-5/bookstore-monolith/src/main/resources/config/liquibase/master.xml @@ -5,6 +5,7 @@ xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd"> + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-delete-dialog.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-delete-dialog.component.html new file mode 100644 index 0000000000..be3647e9df --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-delete-dialog.component.html @@ -0,0 +1,19 @@ +
+ + + +
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-delete-dialog.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-delete-dialog.component.ts new file mode 100644 index 0000000000..7992a5d26d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-delete-dialog.component.ts @@ -0,0 +1,65 @@ +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; + +import { NgbActiveModal, NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { JhiEventManager } from 'ng-jhipster'; + +import { IBook } from 'app/shared/model/book.model'; +import { BookService } from './book.service'; + +@Component({ + selector: 'jhi-book-delete-dialog', + templateUrl: './book-delete-dialog.component.html' +}) +export class BookDeleteDialogComponent { + book: IBook; + + constructor(protected bookService: BookService, public activeModal: NgbActiveModal, protected eventManager: JhiEventManager) {} + + clear() { + this.activeModal.dismiss('cancel'); + } + + confirmDelete(id: number) { + this.bookService.delete(id).subscribe(response => { + this.eventManager.broadcast({ + name: 'bookListModification', + content: 'Deleted an book' + }); + this.activeModal.dismiss(true); + }); + } +} + +@Component({ + selector: 'jhi-book-delete-popup', + template: '' +}) +export class BookDeletePopupComponent implements OnInit, OnDestroy { + protected ngbModalRef: NgbModalRef; + + constructor(protected activatedRoute: ActivatedRoute, protected router: Router, protected modalService: NgbModal) {} + + ngOnInit() { + this.activatedRoute.data.subscribe(({ book }) => { + setTimeout(() => { + this.ngbModalRef = this.modalService.open(BookDeleteDialogComponent as Component, { size: 'lg', backdrop: 'static' }); + this.ngbModalRef.componentInstance.book = book; + this.ngbModalRef.result.then( + result => { + this.router.navigate(['/book', { outlets: { popup: null } }]); + this.ngbModalRef = null; + }, + reason => { + this.router.navigate(['/book', { outlets: { popup: null } }]); + this.ngbModalRef = null; + } + ); + }, 0); + }); + } + + ngOnDestroy() { + this.ngbModalRef = null; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.html new file mode 100644 index 0000000000..0aef73282a --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.html @@ -0,0 +1,43 @@ +
+
+
+

Book {{book.id}}

+
+ +
+
Title
+
+ {{book.title}} +
+
Author
+
+ {{book.author}} +
+
Published
+
+ {{book.published}} +
+
Quantity
+
+ {{book.quantity}} +
+
Price
+
+ {{book.price}} +
+
+ + + + +
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.ts new file mode 100644 index 0000000000..50a6bec9ad --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.ts @@ -0,0 +1,24 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +import { IBook } from 'app/shared/model/book.model'; + +@Component({ + selector: 'jhi-book-detail', + templateUrl: './book-detail.component.html' +}) +export class BookDetailComponent implements OnInit { + book: IBook; + + constructor(protected activatedRoute: ActivatedRoute) {} + + ngOnInit() { + this.activatedRoute.data.subscribe(({ book }) => { + this.book = book; + }); + } + + previousState() { + window.history.back(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-update.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-update.component.html new file mode 100644 index 0000000000..3b41c6e1e0 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-update.component.html @@ -0,0 +1,100 @@ +
+
+
+

Create or edit a Book

+
+ +
+ + +
+
+ + +
+ + This field is required. + +
+
+
+ + +
+ + This field is required. + +
+
+
+ +
+ + + + +
+
+ + This field is required. + +
+
+
+ + +
+ + This field is required. + + + This field should be at least 0. + + + This field should be a number. + +
+
+
+ + +
+ + This field is required. + + + This field should be at least 0. + + + This field should be a number. + +
+
+ +
+
+ + +
+
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-update.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-update.component.ts new file mode 100644 index 0000000000..67f46a67c2 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-update.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { HttpResponse, HttpErrorResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; +import * as moment from 'moment'; +import { IBook } from 'app/shared/model/book.model'; +import { BookService } from './book.service'; + +@Component({ + selector: 'jhi-book-update', + templateUrl: './book-update.component.html' +}) +export class BookUpdateComponent implements OnInit { + book: IBook; + isSaving: boolean; + publishedDp: any; + + constructor(protected bookService: BookService, protected activatedRoute: ActivatedRoute) {} + + ngOnInit() { + this.isSaving = false; + this.activatedRoute.data.subscribe(({ book }) => { + this.book = book; + }); + } + + previousState() { + window.history.back(); + } + + save() { + this.isSaving = true; + if (this.book.id !== undefined) { + this.subscribeToSaveResponse(this.bookService.update(this.book)); + } else { + this.subscribeToSaveResponse(this.bookService.create(this.book)); + } + } + + protected subscribeToSaveResponse(result: Observable>) { + result.subscribe((res: HttpResponse) => this.onSaveSuccess(), (res: HttpErrorResponse) => this.onSaveError()); + } + + protected onSaveSuccess() { + this.isSaving = false; + this.previousState(); + } + + protected onSaveError() { + this.isSaving = false; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.component.html new file mode 100644 index 0000000000..74ad02a8e3 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.component.html @@ -0,0 +1,62 @@ +
+

+ Books + +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
IDTitleAuthorPublishedQuantityPrice
{{book.id}}{{book.title}}{{book.author}}{{book.published | date:'mediumDate'}}{{book.quantity}}{{book.price}} +
+ + + +
+
+
+
diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.component.ts new file mode 100644 index 0000000000..91a71c2f5c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.component.ts @@ -0,0 +1,65 @@ +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; +import { Subscription } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; +import { JhiEventManager, JhiAlertService } from 'ng-jhipster'; + +import { IBook } from 'app/shared/model/book.model'; +import { AccountService } from 'app/core'; +import { BookService } from './book.service'; + +@Component({ + selector: 'jhi-book', + templateUrl: './book.component.html' +}) +export class BookComponent implements OnInit, OnDestroy { + books: IBook[]; + currentAccount: any; + eventSubscriber: Subscription; + + constructor( + protected bookService: BookService, + protected jhiAlertService: JhiAlertService, + protected eventManager: JhiEventManager, + protected accountService: AccountService + ) {} + + loadAll() { + this.bookService + .query() + .pipe( + filter((res: HttpResponse) => res.ok), + map((res: HttpResponse) => res.body) + ) + .subscribe( + (res: IBook[]) => { + this.books = res; + }, + (res: HttpErrorResponse) => this.onError(res.message) + ); + } + + ngOnInit() { + this.loadAll(); + this.accountService.identity().then(account => { + this.currentAccount = account; + }); + this.registerChangeInBooks(); + } + + ngOnDestroy() { + this.eventManager.destroy(this.eventSubscriber); + } + + trackId(index: number, item: IBook) { + return item.id; + } + + registerChangeInBooks() { + this.eventSubscriber = this.eventManager.subscribe('bookListModification', response => this.loadAll()); + } + + protected onError(errorMessage: string) { + this.jhiAlertService.error(errorMessage, null, null); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.module.ts new file mode 100644 index 0000000000..fe221a0eb9 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.module.ts @@ -0,0 +1,23 @@ +import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { RouterModule } from '@angular/router'; + +import { BookstoreSharedModule } from 'app/shared'; +import { + BookComponent, + BookDetailComponent, + BookUpdateComponent, + BookDeletePopupComponent, + BookDeleteDialogComponent, + bookRoute, + bookPopupRoute +} from './'; + +const ENTITY_STATES = [...bookRoute, ...bookPopupRoute]; + +@NgModule({ + imports: [BookstoreSharedModule, RouterModule.forChild(ENTITY_STATES)], + declarations: [BookComponent, BookDetailComponent, BookUpdateComponent, BookDeleteDialogComponent, BookDeletePopupComponent], + entryComponents: [BookComponent, BookUpdateComponent, BookDeleteDialogComponent, BookDeletePopupComponent], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class BookstoreBookModule {} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.route.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.route.ts new file mode 100644 index 0000000000..154fa89a5c --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.route.ts @@ -0,0 +1,93 @@ +import { Injectable } from '@angular/core'; +import { HttpResponse } from '@angular/common/http'; +import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Routes } from '@angular/router'; +import { UserRouteAccessService } from 'app/core'; +import { Observable, of } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; +import { Book } from 'app/shared/model/book.model'; +import { BookService } from './book.service'; +import { BookComponent } from './book.component'; +import { BookDetailComponent } from './book-detail.component'; +import { BookUpdateComponent } from './book-update.component'; +import { BookDeletePopupComponent } from './book-delete-dialog.component'; +import { IBook } from 'app/shared/model/book.model'; + +@Injectable({ providedIn: 'root' }) +export class BookResolve implements Resolve { + constructor(private service: BookService) {} + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + const id = route.params['id'] ? route.params['id'] : null; + if (id) { + return this.service.find(id).pipe( + filter((response: HttpResponse) => response.ok), + map((book: HttpResponse) => book.body) + ); + } + return of(new Book()); + } +} + +export const bookRoute: Routes = [ + { + path: '', + component: BookComponent, + data: { + authorities: ['ROLE_USER'], + pageTitle: 'Books' + }, + canActivate: [UserRouteAccessService] + }, + { + path: ':id/view', + component: BookDetailComponent, + resolve: { + book: BookResolve + }, + data: { + authorities: ['ROLE_USER'], + pageTitle: 'Books' + }, + canActivate: [UserRouteAccessService] + }, + { + path: 'new', + component: BookUpdateComponent, + resolve: { + book: BookResolve + }, + data: { + authorities: ['ROLE_USER'], + pageTitle: 'Books' + }, + canActivate: [UserRouteAccessService] + }, + { + path: ':id/edit', + component: BookUpdateComponent, + resolve: { + book: BookResolve + }, + data: { + authorities: ['ROLE_USER'], + pageTitle: 'Books' + }, + canActivate: [UserRouteAccessService] + } +]; + +export const bookPopupRoute: Routes = [ + { + path: ':id/delete', + component: BookDeletePopupComponent, + resolve: { + book: BookResolve + }, + data: { + authorities: ['ROLE_USER'], + pageTitle: 'Books' + }, + canActivate: [UserRouteAccessService], + outlet: 'popup' + } +]; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.service.ts new file mode 100644 index 0000000000..3ff649d25d --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.service.ts @@ -0,0 +1,74 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import * as moment from 'moment'; +import { DATE_FORMAT } from 'app/shared/constants/input.constants'; +import { map } from 'rxjs/operators'; + +import { SERVER_API_URL } from 'app/app.constants'; +import { createRequestOption } from 'app/shared'; +import { IBook } from 'app/shared/model/book.model'; + +type EntityResponseType = HttpResponse; +type EntityArrayResponseType = HttpResponse; + +@Injectable({ providedIn: 'root' }) +export class BookService { + public resourceUrl = SERVER_API_URL + 'api/books'; + + constructor(protected http: HttpClient) {} + + create(book: IBook): Observable { + const copy = this.convertDateFromClient(book); + return this.http + .post(this.resourceUrl, copy, { observe: 'response' }) + .pipe(map((res: EntityResponseType) => this.convertDateFromServer(res))); + } + + update(book: IBook): Observable { + const copy = this.convertDateFromClient(book); + return this.http + .put(this.resourceUrl, copy, { observe: 'response' }) + .pipe(map((res: EntityResponseType) => this.convertDateFromServer(res))); + } + + find(id: number): Observable { + return this.http + .get(`${this.resourceUrl}/${id}`, { observe: 'response' }) + .pipe(map((res: EntityResponseType) => this.convertDateFromServer(res))); + } + + query(req?: any): Observable { + const options = createRequestOption(req); + return this.http + .get(this.resourceUrl, { params: options, observe: 'response' }) + .pipe(map((res: EntityArrayResponseType) => this.convertDateArrayFromServer(res))); + } + + delete(id: number): Observable> { + return this.http.delete(`${this.resourceUrl}/${id}`, { observe: 'response' }); + } + + protected convertDateFromClient(book: IBook): IBook { + const copy: IBook = Object.assign({}, book, { + published: book.published != null && book.published.isValid() ? book.published.format(DATE_FORMAT) : null + }); + return copy; + } + + protected convertDateFromServer(res: EntityResponseType): EntityResponseType { + if (res.body) { + res.body.published = res.body.published != null ? moment(res.body.published) : null; + } + return res; + } + + protected convertDateArrayFromServer(res: EntityArrayResponseType): EntityArrayResponseType { + if (res.body) { + res.body.forEach((book: IBook) => { + book.published = book.published != null ? moment(book.published) : null; + }); + } + return res; + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/index.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/index.ts new file mode 100644 index 0000000000..603cf68f9f --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/index.ts @@ -0,0 +1,6 @@ +export * from './book.service'; +export * from './book-update.component'; +export * from './book-delete-dialog.component'; +export * from './book-detail.component'; +export * from './book.component'; +export * from './book.route'; diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/entity.module.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/entity.module.ts index b0f67260c7..fba1f55ef7 100644 --- a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/entity.module.ts +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/entity.module.ts @@ -4,6 +4,10 @@ import { RouterModule } from '@angular/router'; @NgModule({ imports: [ RouterModule.forChild([ + { + path: 'book', + loadChildren: './book/book.module#BookstoreBookModule' + } /* jhipster-needle-add-entity-route - JHipster will add entity modules routes here */ ]) ], diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.html index bd3e80b3cb..e58d234c22 100644 --- a/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.html +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/layouts/navbar/navbar.component.html @@ -27,6 +27,12 @@ diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/model/book.model.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/model/book.model.ts new file mode 100644 index 0000000000..ee943a4127 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/shared/model/book.model.ts @@ -0,0 +1,21 @@ +import { Moment } from 'moment'; + +export interface IBook { + id?: number; + title?: string; + author?: string; + published?: Moment; + quantity?: number; + price?: number; +} + +export class Book implements IBook { + constructor( + public id?: number, + public title?: string, + public author?: string, + public published?: Moment, + public quantity?: number, + public price?: number + ) {} +} diff --git a/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/BookResourceIntTest.java b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/BookResourceIntTest.java new file mode 100644 index 0000000000..ef8f27ceea --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/java/com/baeldung/jhipster5/web/rest/BookResourceIntTest.java @@ -0,0 +1,416 @@ +package com.baeldung.jhipster5.web.rest; + +import com.baeldung.jhipster5.BookstoreApp; + +import com.baeldung.jhipster5.domain.Book; +import com.baeldung.jhipster5.repository.BookRepository; +import com.baeldung.jhipster5.service.BookService; +import com.baeldung.jhipster5.service.dto.BookDTO; +import com.baeldung.jhipster5.service.mapper.BookMapper; +import com.baeldung.jhipster5.web.rest.errors.ExceptionTranslator; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.web.PageableHandlerMethodArgumentResolver; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.Validator; + +import javax.persistence.EntityManager; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.List; + + +import static com.baeldung.jhipster5.web.rest.TestUtil.createFormattingConversionService; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +/** + * Test class for the BookResource REST controller. + * + * @see BookResource + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BookstoreApp.class) +public class BookResourceIntTest { + + private static final String DEFAULT_TITLE = "AAAAAAAAAA"; + private static final String UPDATED_TITLE = "BBBBBBBBBB"; + + private static final String DEFAULT_AUTHOR = "AAAAAAAAAA"; + private static final String UPDATED_AUTHOR = "BBBBBBBBBB"; + + private static final LocalDate DEFAULT_PUBLISHED = LocalDate.ofEpochDay(0L); + private static final LocalDate UPDATED_PUBLISHED = LocalDate.now(ZoneId.systemDefault()); + + private static final Integer DEFAULT_QUANTITY = 0; + private static final Integer UPDATED_QUANTITY = 1; + + private static final Double DEFAULT_PRICE = 0D; + private static final Double UPDATED_PRICE = 1D; + + @Autowired + private BookRepository bookRepository; + + @Autowired + private BookMapper bookMapper; + + @Autowired + private BookService bookService; + + @Autowired + private MappingJackson2HttpMessageConverter jacksonMessageConverter; + + @Autowired + private PageableHandlerMethodArgumentResolver pageableArgumentResolver; + + @Autowired + private ExceptionTranslator exceptionTranslator; + + @Autowired + private EntityManager em; + + @Autowired + private Validator validator; + + private MockMvc restBookMockMvc; + + private Book book; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + final BookResource bookResource = new BookResource(bookService); + this.restBookMockMvc = MockMvcBuilders.standaloneSetup(bookResource) + .setCustomArgumentResolvers(pageableArgumentResolver) + .setControllerAdvice(exceptionTranslator) + .setConversionService(createFormattingConversionService()) + .setMessageConverters(jacksonMessageConverter) + .setValidator(validator).build(); + } + + /** + * Create an entity for this test. + * + * This is a static method, as tests for other entities might also need it, + * if they test an entity which requires the current entity. + */ + public static Book createEntity(EntityManager em) { + Book book = new Book() + .title(DEFAULT_TITLE) + .author(DEFAULT_AUTHOR) + .published(DEFAULT_PUBLISHED) + .quantity(DEFAULT_QUANTITY) + .price(DEFAULT_PRICE); + return book; + } + + @Before + public void initTest() { + book = createEntity(em); + } + + @Test + @Transactional + public void createBook() throws Exception { + int databaseSizeBeforeCreate = bookRepository.findAll().size(); + + // Create the Book + BookDTO bookDTO = bookMapper.toDto(book); + restBookMockMvc.perform(post("/api/books") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(bookDTO))) + .andExpect(status().isCreated()); + + // Validate the Book in the database + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeCreate + 1); + Book testBook = bookList.get(bookList.size() - 1); + assertThat(testBook.getTitle()).isEqualTo(DEFAULT_TITLE); + assertThat(testBook.getAuthor()).isEqualTo(DEFAULT_AUTHOR); + assertThat(testBook.getPublished()).isEqualTo(DEFAULT_PUBLISHED); + assertThat(testBook.getQuantity()).isEqualTo(DEFAULT_QUANTITY); + assertThat(testBook.getPrice()).isEqualTo(DEFAULT_PRICE); + } + + @Test + @Transactional + public void createBookWithExistingId() throws Exception { + int databaseSizeBeforeCreate = bookRepository.findAll().size(); + + // Create the Book with an existing ID + book.setId(1L); + BookDTO bookDTO = bookMapper.toDto(book); + + // An entity with an existing ID cannot be created, so this API call must fail + restBookMockMvc.perform(post("/api/books") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(bookDTO))) + .andExpect(status().isBadRequest()); + + // Validate the Book in the database + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeCreate); + } + + @Test + @Transactional + public void checkTitleIsRequired() throws Exception { + int databaseSizeBeforeTest = bookRepository.findAll().size(); + // set the field null + book.setTitle(null); + + // Create the Book, which fails. + BookDTO bookDTO = bookMapper.toDto(book); + + restBookMockMvc.perform(post("/api/books") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(bookDTO))) + .andExpect(status().isBadRequest()); + + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeTest); + } + + @Test + @Transactional + public void checkAuthorIsRequired() throws Exception { + int databaseSizeBeforeTest = bookRepository.findAll().size(); + // set the field null + book.setAuthor(null); + + // Create the Book, which fails. + BookDTO bookDTO = bookMapper.toDto(book); + + restBookMockMvc.perform(post("/api/books") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(bookDTO))) + .andExpect(status().isBadRequest()); + + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeTest); + } + + @Test + @Transactional + public void checkPublishedIsRequired() throws Exception { + int databaseSizeBeforeTest = bookRepository.findAll().size(); + // set the field null + book.setPublished(null); + + // Create the Book, which fails. + BookDTO bookDTO = bookMapper.toDto(book); + + restBookMockMvc.perform(post("/api/books") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(bookDTO))) + .andExpect(status().isBadRequest()); + + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeTest); + } + + @Test + @Transactional + public void checkQuantityIsRequired() throws Exception { + int databaseSizeBeforeTest = bookRepository.findAll().size(); + // set the field null + book.setQuantity(null); + + // Create the Book, which fails. + BookDTO bookDTO = bookMapper.toDto(book); + + restBookMockMvc.perform(post("/api/books") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(bookDTO))) + .andExpect(status().isBadRequest()); + + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeTest); + } + + @Test + @Transactional + public void checkPriceIsRequired() throws Exception { + int databaseSizeBeforeTest = bookRepository.findAll().size(); + // set the field null + book.setPrice(null); + + // Create the Book, which fails. + BookDTO bookDTO = bookMapper.toDto(book); + + restBookMockMvc.perform(post("/api/books") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(bookDTO))) + .andExpect(status().isBadRequest()); + + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeTest); + } + + @Test + @Transactional + public void getAllBooks() throws Exception { + // Initialize the database + bookRepository.saveAndFlush(book); + + // Get all the bookList + restBookMockMvc.perform(get("/api/books?sort=id,desc")) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(jsonPath("$.[*].id").value(hasItem(book.getId().intValue()))) + .andExpect(jsonPath("$.[*].title").value(hasItem(DEFAULT_TITLE.toString()))) + .andExpect(jsonPath("$.[*].author").value(hasItem(DEFAULT_AUTHOR.toString()))) + .andExpect(jsonPath("$.[*].published").value(hasItem(DEFAULT_PUBLISHED.toString()))) + .andExpect(jsonPath("$.[*].quantity").value(hasItem(DEFAULT_QUANTITY))) + .andExpect(jsonPath("$.[*].price").value(hasItem(DEFAULT_PRICE.doubleValue()))); + } + + @Test + @Transactional + public void getBook() throws Exception { + // Initialize the database + bookRepository.saveAndFlush(book); + + // Get the book + restBookMockMvc.perform(get("/api/books/{id}", book.getId())) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)) + .andExpect(jsonPath("$.id").value(book.getId().intValue())) + .andExpect(jsonPath("$.title").value(DEFAULT_TITLE.toString())) + .andExpect(jsonPath("$.author").value(DEFAULT_AUTHOR.toString())) + .andExpect(jsonPath("$.published").value(DEFAULT_PUBLISHED.toString())) + .andExpect(jsonPath("$.quantity").value(DEFAULT_QUANTITY)) + .andExpect(jsonPath("$.price").value(DEFAULT_PRICE.doubleValue())); + } + + @Test + @Transactional + public void getNonExistingBook() throws Exception { + // Get the book + restBookMockMvc.perform(get("/api/books/{id}", Long.MAX_VALUE)) + .andExpect(status().isNotFound()); + } + + @Test + @Transactional + public void updateBook() throws Exception { + // Initialize the database + bookRepository.saveAndFlush(book); + + int databaseSizeBeforeUpdate = bookRepository.findAll().size(); + + // Update the book + Book updatedBook = bookRepository.findById(book.getId()).get(); + // Disconnect from session so that the updates on updatedBook are not directly saved in db + em.detach(updatedBook); + updatedBook + .title(UPDATED_TITLE) + .author(UPDATED_AUTHOR) + .published(UPDATED_PUBLISHED) + .quantity(UPDATED_QUANTITY) + .price(UPDATED_PRICE); + BookDTO bookDTO = bookMapper.toDto(updatedBook); + + restBookMockMvc.perform(put("/api/books") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(bookDTO))) + .andExpect(status().isOk()); + + // Validate the Book in the database + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeUpdate); + Book testBook = bookList.get(bookList.size() - 1); + assertThat(testBook.getTitle()).isEqualTo(UPDATED_TITLE); + assertThat(testBook.getAuthor()).isEqualTo(UPDATED_AUTHOR); + assertThat(testBook.getPublished()).isEqualTo(UPDATED_PUBLISHED); + assertThat(testBook.getQuantity()).isEqualTo(UPDATED_QUANTITY); + assertThat(testBook.getPrice()).isEqualTo(UPDATED_PRICE); + } + + @Test + @Transactional + public void updateNonExistingBook() throws Exception { + int databaseSizeBeforeUpdate = bookRepository.findAll().size(); + + // Create the Book + BookDTO bookDTO = bookMapper.toDto(book); + + // If the entity doesn't have an ID, it will throw BadRequestAlertException + restBookMockMvc.perform(put("/api/books") + .contentType(TestUtil.APPLICATION_JSON_UTF8) + .content(TestUtil.convertObjectToJsonBytes(bookDTO))) + .andExpect(status().isBadRequest()); + + // Validate the Book in the database + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeUpdate); + } + + @Test + @Transactional + public void deleteBook() throws Exception { + // Initialize the database + bookRepository.saveAndFlush(book); + + int databaseSizeBeforeDelete = bookRepository.findAll().size(); + + // Delete the book + restBookMockMvc.perform(delete("/api/books/{id}", book.getId()) + .accept(TestUtil.APPLICATION_JSON_UTF8)) + .andExpect(status().isOk()); + + // Validate the database is empty + List bookList = bookRepository.findAll(); + assertThat(bookList).hasSize(databaseSizeBeforeDelete - 1); + } + + @Test + @Transactional + public void equalsVerifier() throws Exception { + TestUtil.equalsVerifier(Book.class); + Book book1 = new Book(); + book1.setId(1L); + Book book2 = new Book(); + book2.setId(book1.getId()); + assertThat(book1).isEqualTo(book2); + book2.setId(2L); + assertThat(book1).isNotEqualTo(book2); + book1.setId(null); + assertThat(book1).isNotEqualTo(book2); + } + + @Test + @Transactional + public void dtoEqualsVerifier() throws Exception { + TestUtil.equalsVerifier(BookDTO.class); + BookDTO bookDTO1 = new BookDTO(); + bookDTO1.setId(1L); + BookDTO bookDTO2 = new BookDTO(); + assertThat(bookDTO1).isNotEqualTo(bookDTO2); + bookDTO2.setId(bookDTO1.getId()); + assertThat(bookDTO1).isEqualTo(bookDTO2); + bookDTO2.setId(2L); + assertThat(bookDTO1).isNotEqualTo(bookDTO2); + bookDTO1.setId(null); + assertThat(bookDTO1).isNotEqualTo(bookDTO2); + } + + @Test + @Transactional + public void testEntityFromId() { + assertThat(bookMapper.fromId(42L).getId()).isEqualTo(42); + assertThat(bookMapper.fromId(null)).isNull(); + } +} diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-delete-dialog.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-delete-dialog.component.spec.ts new file mode 100644 index 0000000000..6ffba6ee1e --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-delete-dialog.component.spec.ts @@ -0,0 +1,52 @@ +/* tslint:disable max-line-length */ +import { ComponentFixture, TestBed, inject, fakeAsync, tick } from '@angular/core/testing'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { Observable, of } from 'rxjs'; +import { JhiEventManager } from 'ng-jhipster'; + +import { BookstoreTestModule } from '../../../test.module'; +import { BookDeleteDialogComponent } from 'app/entities/book/book-delete-dialog.component'; +import { BookService } from 'app/entities/book/book.service'; + +describe('Component Tests', () => { + describe('Book Management Delete Component', () => { + let comp: BookDeleteDialogComponent; + let fixture: ComponentFixture; + let service: BookService; + let mockEventManager: any; + let mockActiveModal: any; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [BookDeleteDialogComponent] + }) + .overrideTemplate(BookDeleteDialogComponent, '') + .compileComponents(); + fixture = TestBed.createComponent(BookDeleteDialogComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(BookService); + mockEventManager = fixture.debugElement.injector.get(JhiEventManager); + mockActiveModal = fixture.debugElement.injector.get(NgbActiveModal); + }); + + describe('confirmDelete', () => { + it('Should call delete service on confirmDelete', inject( + [], + fakeAsync(() => { + // GIVEN + spyOn(service, 'delete').and.returnValue(of({})); + + // WHEN + comp.confirmDelete(123); + tick(); + + // THEN + expect(service.delete).toHaveBeenCalledWith(123); + expect(mockActiveModal.dismissSpy).toHaveBeenCalled(); + expect(mockEventManager.broadcastSpy).toHaveBeenCalled(); + }) + )); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-detail.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-detail.component.spec.ts new file mode 100644 index 0000000000..b0ff94b3ea --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-detail.component.spec.ts @@ -0,0 +1,40 @@ +/* tslint:disable max-line-length */ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ActivatedRoute } from '@angular/router'; +import { of } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { BookDetailComponent } from 'app/entities/book/book-detail.component'; +import { Book } from 'app/shared/model/book.model'; + +describe('Component Tests', () => { + describe('Book Management Detail Component', () => { + let comp: BookDetailComponent; + let fixture: ComponentFixture; + const route = ({ data: of({ book: new Book(123) }) } as any) as ActivatedRoute; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [BookDetailComponent], + providers: [{ provide: ActivatedRoute, useValue: route }] + }) + .overrideTemplate(BookDetailComponent, '') + .compileComponents(); + fixture = TestBed.createComponent(BookDetailComponent); + comp = fixture.componentInstance; + }); + + describe('OnInit', () => { + it('Should call load all on init', () => { + // GIVEN + + // WHEN + comp.ngOnInit(); + + // THEN + expect(comp.book).toEqual(jasmine.objectContaining({ id: 123 })); + }); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-update.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-update.component.spec.ts new file mode 100644 index 0000000000..336a2e2397 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book-update.component.spec.ts @@ -0,0 +1,60 @@ +/* tslint:disable max-line-length */ +import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; +import { HttpResponse } from '@angular/common/http'; +import { Observable, of } from 'rxjs'; + +import { BookstoreTestModule } from '../../../test.module'; +import { BookUpdateComponent } from 'app/entities/book/book-update.component'; +import { BookService } from 'app/entities/book/book.service'; +import { Book } from 'app/shared/model/book.model'; + +describe('Component Tests', () => { + describe('Book Management Update Component', () => { + let comp: BookUpdateComponent; + let fixture: ComponentFixture; + let service: BookService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [BookUpdateComponent] + }) + .overrideTemplate(BookUpdateComponent, '') + .compileComponents(); + + fixture = TestBed.createComponent(BookUpdateComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(BookService); + }); + + describe('save', () => { + it('Should call update service on save for existing entity', fakeAsync(() => { + // GIVEN + const entity = new Book(123); + spyOn(service, 'update').and.returnValue(of(new HttpResponse({ body: entity }))); + comp.book = entity; + // WHEN + comp.save(); + tick(); // simulate async + + // THEN + expect(service.update).toHaveBeenCalledWith(entity); + expect(comp.isSaving).toEqual(false); + })); + + it('Should call create service on save for new entity', fakeAsync(() => { + // GIVEN + const entity = new Book(); + spyOn(service, 'create').and.returnValue(of(new HttpResponse({ body: entity }))); + comp.book = entity; + // WHEN + comp.save(); + tick(); // simulate async + + // THEN + expect(service.create).toHaveBeenCalledWith(entity); + expect(comp.isSaving).toEqual(false); + })); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book.component.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book.component.spec.ts new file mode 100644 index 0000000000..3b3d472650 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book.component.spec.ts @@ -0,0 +1,51 @@ +/* tslint:disable max-line-length */ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Observable, of } from 'rxjs'; +import { HttpHeaders, HttpResponse } from '@angular/common/http'; + +import { BookstoreTestModule } from '../../../test.module'; +import { BookComponent } from 'app/entities/book/book.component'; +import { BookService } from 'app/entities/book/book.service'; +import { Book } from 'app/shared/model/book.model'; + +describe('Component Tests', () => { + describe('Book Management Component', () => { + let comp: BookComponent; + let fixture: ComponentFixture; + let service: BookService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [BookstoreTestModule], + declarations: [BookComponent], + providers: [] + }) + .overrideTemplate(BookComponent, '') + .compileComponents(); + + fixture = TestBed.createComponent(BookComponent); + comp = fixture.componentInstance; + service = fixture.debugElement.injector.get(BookService); + }); + + it('Should call load all on init', () => { + // GIVEN + const headers = new HttpHeaders().append('link', 'link;link'); + spyOn(service, 'query').and.returnValue( + of( + new HttpResponse({ + body: [new Book(123)], + headers + }) + ) + ); + + // WHEN + comp.ngOnInit(); + + // THEN + expect(service.query).toHaveBeenCalled(); + expect(comp.books[0]).toEqual(jasmine.objectContaining({ id: 123 })); + }); + }); +}); diff --git a/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book.service.spec.ts b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book.service.spec.ts new file mode 100644 index 0000000000..cd0c5b7318 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/test/javascript/spec/app/entities/book/book.service.spec.ts @@ -0,0 +1,137 @@ +/* tslint:disable max-line-length */ +import { TestBed, getTestBed } from '@angular/core/testing'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { HttpClient, HttpResponse } from '@angular/common/http'; +import { of } from 'rxjs'; +import { take, map } from 'rxjs/operators'; +import * as moment from 'moment'; +import { DATE_FORMAT } from 'app/shared/constants/input.constants'; +import { BookService } from 'app/entities/book/book.service'; +import { IBook, Book } from 'app/shared/model/book.model'; + +describe('Service Tests', () => { + describe('Book Service', () => { + let injector: TestBed; + let service: BookService; + let httpMock: HttpTestingController; + let elemDefault: IBook; + let currentDate: moment.Moment; + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule] + }); + injector = getTestBed(); + service = injector.get(BookService); + httpMock = injector.get(HttpTestingController); + currentDate = moment(); + + elemDefault = new Book(0, 'AAAAAAA', 'AAAAAAA', currentDate, 0, 0); + }); + + describe('Service methods', async () => { + it('should find an element', async () => { + const returnedFromService = Object.assign( + { + published: currentDate.format(DATE_FORMAT) + }, + elemDefault + ); + service + .find(123) + .pipe(take(1)) + .subscribe(resp => expect(resp).toMatchObject({ body: elemDefault })); + + const req = httpMock.expectOne({ method: 'GET' }); + req.flush(JSON.stringify(returnedFromService)); + }); + + it('should create a Book', async () => { + const returnedFromService = Object.assign( + { + id: 0, + published: currentDate.format(DATE_FORMAT) + }, + elemDefault + ); + const expected = Object.assign( + { + published: currentDate + }, + returnedFromService + ); + service + .create(new Book(null)) + .pipe(take(1)) + .subscribe(resp => expect(resp).toMatchObject({ body: expected })); + const req = httpMock.expectOne({ method: 'POST' }); + req.flush(JSON.stringify(returnedFromService)); + }); + + it('should update a Book', async () => { + const returnedFromService = Object.assign( + { + title: 'BBBBBB', + author: 'BBBBBB', + published: currentDate.format(DATE_FORMAT), + quantity: 1, + price: 1 + }, + elemDefault + ); + + const expected = Object.assign( + { + published: currentDate + }, + returnedFromService + ); + service + .update(expected) + .pipe(take(1)) + .subscribe(resp => expect(resp).toMatchObject({ body: expected })); + const req = httpMock.expectOne({ method: 'PUT' }); + req.flush(JSON.stringify(returnedFromService)); + }); + + it('should return a list of Book', async () => { + const returnedFromService = Object.assign( + { + title: 'BBBBBB', + author: 'BBBBBB', + published: currentDate.format(DATE_FORMAT), + quantity: 1, + price: 1 + }, + elemDefault + ); + const expected = Object.assign( + { + published: currentDate + }, + returnedFromService + ); + service + .query(expected) + .pipe( + take(1), + map(resp => resp.body) + ) + .subscribe(body => expect(body).toContainEqual(expected)); + const req = httpMock.expectOne({ method: 'GET' }); + req.flush(JSON.stringify([returnedFromService])); + httpMock.verify(); + }); + + it('should delete a Book', async () => { + const rxPromise = service.delete(123).subscribe(resp => expect(resp.ok)); + + const req = httpMock.expectOne({ method: 'DELETE' }); + req.flush({ status: 200 }); + }); + }); + + afterEach(() => { + httpMock.verify(); + }); + }); +}); From 39a0eda4379b7779ecd170ea61b48d3f49094ea6 Mon Sep 17 00:00:00 2001 From: Andrey Shcherbakov Date: Tue, 19 Mar 2019 15:45:25 +0100 Subject: [PATCH 416/496] Remove ValidationUnitTest.kt (#6562) --- .../baeldung/annotations/ValidationTest.kt | 2 +- .../annotations/ValidationUnitTest.kt | 42 ------------------- 2 files changed, 1 insertion(+), 43 deletions(-) delete mode 100644 core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationUnitTest.kt diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt index 97fb3434ee..5c2b6ef47f 100644 --- a/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt +++ b/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt @@ -4,7 +4,7 @@ import org.junit.Test import kotlin.test.assertTrue import kotlin.test.assertFalse -class ValidationUnitTest { +class ValidationTest { @Test fun whenAmountIsOneAndNameIsAlice_thenTrue() { diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationUnitTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationUnitTest.kt deleted file mode 100644 index 506b7a24b5..0000000000 --- a/core-kotlin-2/src/test/kotlin/com/baeldung/annotations/ValidationUnitTest.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.annotations - -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Test - - -class ValidationUnitTest { - - @Test - fun whenAmountIsOneAndNameIsAlice_thenTrue() { - assertTrue(Validator().isValid(Item(1f, "Alice"))) - } - - @Test - fun whenAmountIsOneAndNameIsBob_thenTrue() { - assertTrue(Validator().isValid(Item(1f, "Bob"))) - } - - - @Test - fun whenAmountIsMinusOneAndNameIsAlice_thenFalse() { - assertFalse(Validator().isValid(Item(-1f, "Alice"))) - } - - @Test - fun whenAmountIsMinusOneAndNameIsBob_thenFalse() { - assertFalse(Validator().isValid(Item(-1f, "Bob"))) - } - - @Test - fun whenAmountIsOneAndNameIsTom_thenFalse() { - assertFalse(Validator().isValid(Item(1f, "Tom"))) - } - - @Test - fun whenAmountIsMinusOneAndNameIsTom_thenFalse() { - assertFalse(Validator().isValid(Item(-1f, "Tom"))) - } - - -} \ No newline at end of file From e813a0e64d9828f00643185d5232dacfdf452dc9 Mon Sep 17 00:00:00 2001 From: isaolmez Date: Tue, 19 Mar 2019 22:29:12 +0300 Subject: [PATCH 417/496] BAEL-2715: Modified tests and configurations --- ....java => CustomNettyWebServerFactory.java} | 35 ++++-------- .../{server => }/GreetingController.java | 2 +- .../{server => }/GreetingService.java | 2 +- .../NettyWebServerFactoryPortCustomizer.java | 30 ++++++++++ .../NettyWebServerFactorySslCustomizer.java | 2 +- .../serverconfig/ServerConfigApplication.java | 4 -- .../client/GreetingWebClient.java | 37 ------------ .../GreetingControllerIntegrationTest.java | 8 +-- .../serverconfig/GreetingLiveTest.java | 56 +++++++++++++++++++ .../GreetingSkipAutoConfigLiveTest.java | 8 +++ 10 files changed, 113 insertions(+), 71 deletions(-) rename spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/{server/NettyWebServerFactoryBootstrapCustomizer.java => CustomNettyWebServerFactory.java} (51%) rename spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/{server => }/GreetingController.java (94%) rename spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/{server => }/GreetingService.java (84%) create mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactoryPortCustomizer.java rename spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/{server => }/NettyWebServerFactorySslCustomizer.java (96%) delete mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java rename spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/{server => }/GreetingControllerIntegrationTest.java (87%) create mode 100644 spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingLiveTest.java create mode 100644 spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingSkipAutoConfigLiveTest.java diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryBootstrapCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java similarity index 51% rename from spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryBootstrapCustomizer.java rename to spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java index 05b2fbb7f7..32e57d2d98 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactoryBootstrapCustomizer.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java @@ -1,35 +1,24 @@ -package com.baeldung.serverconfig.server; +package com.baeldung.serverconfig; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; -import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.stereotype.Component; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import reactor.netty.http.server.HttpServer; -@Component -public class NettyWebServerFactoryBootstrapCustomizer implements WebServerFactoryCustomizer { +@Configuration +@Profile("skipAutoConfig") +public class CustomNettyWebServerFactory { - @Override - public void customize(NettyReactiveWebServerFactory serverFactory) { - serverFactory.addServerCustomizers(new PortCustomizer(8443)); - serverFactory.addServerCustomizers(new EventLoopNettyCustomizer()); - } - - private static class PortCustomizer implements NettyServerCustomizer { - - private final int port; - - private PortCustomizer(int port) { - this.port = port; - } - - @Override - public HttpServer apply(HttpServer httpServer) { - return httpServer.port(port); - } + @Bean + public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() { + NettyReactiveWebServerFactory webServerFactory = new NettyReactiveWebServerFactory(); + webServerFactory.addServerCustomizers(new EventLoopNettyCustomizer()); + return webServerFactory; } private static class EventLoopNettyCustomizer implements NettyServerCustomizer { diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingController.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingController.java similarity index 94% rename from spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingController.java rename to spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingController.java index 275439a66f..9cb5b27ac5 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingController.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingController.java @@ -1,4 +1,4 @@ -package com.baeldung.serverconfig.server; +package com.baeldung.serverconfig; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingService.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingService.java similarity index 84% rename from spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingService.java rename to spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingService.java index 5b2b246531..5440f526aa 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/GreetingService.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingService.java @@ -1,4 +1,4 @@ -package com.baeldung.serverconfig.server; +package com.baeldung.serverconfig; import org.springframework.stereotype.Service; import reactor.core.publisher.Mono; diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactoryPortCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactoryPortCustomizer.java new file mode 100644 index 0000000000..152e1285aa --- /dev/null +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactoryPortCustomizer.java @@ -0,0 +1,30 @@ +package com.baeldung.serverconfig; + +import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.stereotype.Component; +import reactor.netty.http.server.HttpServer; + +@Component +public class NettyWebServerFactoryPortCustomizer implements WebServerFactoryCustomizer { + + @Override + public void customize(NettyReactiveWebServerFactory serverFactory) { + serverFactory.addServerCustomizers(new PortCustomizer(8443)); + } + + private static class PortCustomizer implements NettyServerCustomizer { + + private final int port; + + private PortCustomizer(int port) { + this.port = port; + } + + @Override + public HttpServer apply(HttpServer httpServer) { + return httpServer.port(port); + } + } +} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactorySslCustomizer.java similarity index 96% rename from spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java rename to spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactorySslCustomizer.java index d03c3a7f40..d0ad0dcac5 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/server/NettyWebServerFactorySslCustomizer.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactorySslCustomizer.java @@ -1,4 +1,4 @@ -package com.baeldung.serverconfig.server; +package com.baeldung.serverconfig; import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.boot.web.embedded.netty.SslServerCustomizer; diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java index c4ff9c3930..9d420cc7da 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java @@ -1,6 +1,5 @@ package com.baeldung.serverconfig; -import com.baeldung.serverconfig.client.GreetingWebClient; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -9,8 +8,5 @@ public class ServerConfigApplication { public static void main(String[] args) { SpringApplication.run(ServerConfigApplication.class, args); - - GreetingWebClient webClient = new GreetingWebClient(); - webClient.getResult(); } } diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java deleted file mode 100644 index 77dc98398b..0000000000 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/client/GreetingWebClient.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.baeldung.serverconfig.client; - -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import lombok.SneakyThrows; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; -import reactor.netty.http.client.HttpClient; - -public class GreetingWebClient { - - private WebClient client = getWebClient(); - - public void getResult() { - System.out.println("Mono"); - Mono greetingMono = client.get() - .uri("/greet/{name}", "baeldung") - .retrieve() - .bodyToMono(String.class); - - greetingMono.subscribe(System.out::println); - } - - @SneakyThrows - private WebClient getWebClient() { - SslContext sslContext = SslContextBuilder - .forClient() - .trustManager(InsecureTrustManagerFactory.INSTANCE) - .build(); - HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext)); - return WebClient.builder() - .baseUrl("https://localhost:8443") - .clientConnector(new ReactorClientHttpConnector(httpClient)).build(); - } -} diff --git a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingControllerIntegrationTest.java similarity index 87% rename from spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java rename to spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingControllerIntegrationTest.java index f8e384fb6e..3c2c08321a 100644 --- a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/server/GreetingControllerIntegrationTest.java +++ b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingControllerIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.serverconfig.server; +package com.baeldung.serverconfig; import static org.mockito.Mockito.when; @@ -22,11 +22,11 @@ public class GreetingControllerIntegrationTest { @MockBean private GreetingService greetingService; - private final String name = "baeldung"; + private final String name = "Baeldung"; @Before public void setUp() { - when(greetingService.greet(name)).thenReturn(Mono.just("Hello baeldung")); + when(greetingService.greet(name)).thenReturn(Mono.just("Greeting Baeldung")); } @Test @@ -36,6 +36,6 @@ public class GreetingControllerIntegrationTest { .expectStatus() .isOk() .expectBody(String.class) - .isEqualTo("Hello baeldung"); + .isEqualTo("Greeting Baeldung"); } } diff --git a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingLiveTest.java b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingLiveTest.java new file mode 100644 index 0000000000..7c4a37c890 --- /dev/null +++ b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingLiveTest.java @@ -0,0 +1,56 @@ +package com.baeldung.serverconfig; + +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +import javax.net.ssl.SSLException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec; +import reactor.netty.http.client.HttpClient; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT) +public class GreetingLiveTest { + + private static final String BASE_URL = "https://localhost:8443"; + + private WebTestClient webTestClient; + + @Before + public void setup() throws SSLException { + webTestClient = WebTestClient.bindToServer(getConnector()) + .baseUrl(BASE_URL) + .build(); + } + + @Test + public void shouldGreet() { + final String name = "Baeldung"; + + ResponseSpec response = webTestClient.get() + .uri("/greet/{name}", name) + .exchange(); + + response.expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo("Greeting Baeldung"); + } + + private ReactorClientHttpConnector getConnector() throws SSLException { + SslContext sslContext = SslContextBuilder + .forClient() + .trustManager(InsecureTrustManagerFactory.INSTANCE) + .build(); + HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext)); + return new ReactorClientHttpConnector(httpClient); + } +} diff --git a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingSkipAutoConfigLiveTest.java b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingSkipAutoConfigLiveTest.java new file mode 100644 index 0000000000..646742b3d7 --- /dev/null +++ b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingSkipAutoConfigLiveTest.java @@ -0,0 +1,8 @@ +package com.baeldung.serverconfig; + +import org.springframework.test.context.ActiveProfiles; + +@ActiveProfiles("skipAutoConfig") +public class GreetingSkipAutoConfigLiveTest extends GreetingLiveTest { + +} From ddcc4964688a1a2a21119c85dfb02cdb237d571b Mon Sep 17 00:00:00 2001 From: isaolmez Date: Tue, 19 Mar 2019 22:44:07 +0300 Subject: [PATCH 418/496] BAEL-2715: Modified tests and configurations --- .../com/baeldung/serverconfig/CustomNettyWebServerFactory.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java index 32e57d2d98..8a1cdbba97 100644 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java +++ b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java @@ -31,8 +31,6 @@ public class CustomNettyWebServerFactory { .tcpConfiguration(tcpServer -> tcpServer.bootstrap( serverBootstrap -> serverBootstrap.group(parentGroup, childGroup).channel(NioServerSocketChannel.class) )); - } - } } From 88ca90327cad42fa560d283707c99cc278f9dc48 Mon Sep 17 00:00:00 2001 From: enpy Date: Wed, 20 Mar 2019 03:59:02 +0100 Subject: [PATCH 419/496] BAEL 2730 (#6524) * BAEL 2730 * jackson-dataformat-xml uncommented --- .../web/controller/students/Student.java | 53 +++++++++++++ .../students/StudentController.java | 73 ++++++++++++++++++ .../controller/students/StudentService.java | 51 +++++++++++++ .../web/StudentControllerIntegrationTest.java | 76 +++++++++++++++++++ 4 files changed, 253 insertions(+) create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/controller/students/Student.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/controller/students/StudentController.java create mode 100644 spring-boot-rest/src/main/java/com/baeldung/web/controller/students/StudentService.java create mode 100644 spring-boot-rest/src/test/java/com/baeldung/web/StudentControllerIntegrationTest.java diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/students/Student.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/students/Student.java new file mode 100644 index 0000000000..3b6a5c0298 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/students/Student.java @@ -0,0 +1,53 @@ +package com.baeldung.web.controller.students; + +public class Student { + + private long id; + private String firstName; + private String lastName; + + public Student() {} + + public Student(String firstName, String lastName) { + super(); + this.firstName = firstName; + this.lastName = lastName; + } + + public Student(long id, String firstName, String lastName) { + super(); + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public String toString() { + return "Student [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]"; + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/students/StudentController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/students/StudentController.java new file mode 100644 index 0000000000..f937e0c757 --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/students/StudentController.java @@ -0,0 +1,73 @@ +package com.baeldung.web.controller.students; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import com.baeldung.web.controller.students.StudentService; + +@RestController +@RequestMapping("/students") +public class StudentController { + + @Autowired + private StudentService service; + + @GetMapping("/") + public List read() { + return service.readAll(); + } + + @GetMapping("/{id}") + public ResponseEntity read(@PathVariable("id") Long id) { + Student foundStudent = service.read(id); + if (foundStudent == null) { + return ResponseEntity.notFound().build(); + } else { + return ResponseEntity.ok(foundStudent); + } + } + + @PostMapping("/") + public ResponseEntity create(@RequestBody Student student) throws URISyntaxException { + Student createdStudent = service.create(student); + + URI uri = ServletUriComponentsBuilder.fromCurrentRequest() + .path("/{id}") + .buildAndExpand(createdStudent.getId()) + .toUri(); + + return ResponseEntity.created(uri) + .body(createdStudent); + + } + + @PutMapping("/{id}") + public ResponseEntity update(@RequestBody Student student, @PathVariable Long id) { + Student updatedStudent = service.update(id, student); + if (updatedStudent == null) { + return ResponseEntity.notFound().build(); + } else { + return ResponseEntity.ok(updatedStudent); + } + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteStudent(@PathVariable Long id) { + service.delete(id); + + return ResponseEntity.noContent().build(); + } + +} diff --git a/spring-boot-rest/src/main/java/com/baeldung/web/controller/students/StudentService.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/students/StudentService.java new file mode 100644 index 0000000000..d923f4f14f --- /dev/null +++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/students/StudentService.java @@ -0,0 +1,51 @@ +package com.baeldung.web.controller.students; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; + +@Service +public class StudentService { + + // DB repository mock + private Map repository = Arrays.asList( + new Student[]{ + new Student(1, "Alan","Turing"), + new Student(2, "Sebastian","Bach"), + new Student(3, "Pablo","Picasso"), + }).stream() + .collect(Collectors.toConcurrentMap(s -> s.getId(), Function.identity())); + + // DB id sequence mock + private AtomicLong sequence = new AtomicLong(3); + + public List readAll() { + return repository.values().stream().collect(Collectors.toList()); + } + + public Student read(Long id) { + return repository.get(id); + } + + public Student create(Student student) { + long key = sequence.incrementAndGet(); + student.setId(key); + repository.put(key, student); + return student; + } + + public Student update(Long id, Student student) { + student.setId(id); + Student oldStudent = repository.replace(id, student); + return oldStudent == null ? null : student; + } + + public void delete(Long id) { + repository.remove(id); + } +} diff --git a/spring-boot-rest/src/test/java/com/baeldung/web/StudentControllerIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/web/StudentControllerIntegrationTest.java new file mode 100644 index 0000000000..54ac69ebeb --- /dev/null +++ b/spring-boot-rest/src/test/java/com/baeldung/web/StudentControllerIntegrationTest.java @@ -0,0 +1,76 @@ +package com.baeldung.web; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.server.MediaTypeNotSupportedStatusException; + +import com.baeldung.web.controller.students.Student; +import com.fasterxml.jackson.databind.ObjectMapper; + +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class StudentControllerIntegrationTest { + + private static final String STUDENTS_PATH = "/students/"; + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenReadAll_thenStatusIsOk() throws Exception { + this.mockMvc.perform(get(STUDENTS_PATH)) + .andExpect(status().isOk()); + } + + @Test + public void whenReadOne_thenStatusIsOk() throws Exception { + this.mockMvc.perform(get(STUDENTS_PATH + 1)) + .andExpect(status().isOk()); + } + + @Test + public void whenCreate_thenStatusIsCreated() throws Exception { + Student student = new Student(10, "Albert", "Einstein"); + this.mockMvc.perform(post(STUDENTS_PATH).content(asJsonString(student)) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isCreated()); + } + + @Test + public void whenUpdate_thenStatusIsOk() throws Exception { + Student student = new Student(1, "Nikola", "Tesla"); + this.mockMvc.perform(put(STUDENTS_PATH + 1) + .content(asJsonString(student)) + .contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(status().isOk()); + } + + @Test + public void whenDelete_thenStatusIsNoContent() throws Exception { + this.mockMvc.perform(delete(STUDENTS_PATH + 3)) + .andExpect(status().isNoContent()); + } + + private String asJsonString(final Object obj) { + try { + return new ObjectMapper().writeValueAsString(obj); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} From a6e573b363f933e9e137d7702c7d393318be868b Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 19 Mar 2019 21:31:28 -0600 Subject: [PATCH 420/496] Implement code for new JHipster article --- .../config/SecurityConfiguration.java | 1 + .../jhipster5/service/BookService.java | 7 +++++++ .../service/impl/BookServiceImpl.java | 19 +++++++++++++++++++ .../jhipster5/web/rest/BookResource.java | 6 ++++++ .../entities/book/book-detail.component.html | 6 ++++++ .../entities/book/book-detail.component.ts | 14 +++++++++++++- .../webapp/app/entities/book/book.service.ts | 7 +++++++ 7 files changed, 59 insertions(+), 1 deletion(-) diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/SecurityConfiguration.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/SecurityConfiguration.java index 64111588f6..f07944271e 100644 --- a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/SecurityConfiguration.java +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/SecurityConfiguration.java @@ -101,6 +101,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter { .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() + .antMatchers("/api/books/purchase/**").authenticated() .antMatchers("/api/register").permitAll() .antMatchers("/api/activate").permitAll() .antMatchers("/api/authenticate").permitAll() diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java index bb052dc03c..6422d1a424 100644 --- a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/BookService.java @@ -40,4 +40,11 @@ public interface BookService { * @param id the id of the entity */ void delete(Long id); + + /** + * Simulates purchasing a book by reducing the stock of a book by 1. + * @param id the id of the book + * @return Updated BookDTO, empty if not found, or throws exception if an error occurs. + */ + Optional purchase(Long id); } diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java index 00f68b84af..23cd59584c 100644 --- a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/service/impl/BookServiceImpl.java @@ -5,6 +5,7 @@ import com.baeldung.jhipster5.domain.Book; import com.baeldung.jhipster5.repository.BookRepository; import com.baeldung.jhipster5.service.dto.BookDTO; import com.baeldung.jhipster5.service.mapper.BookMapper; +import com.baeldung.jhipster5.web.rest.errors.BadRequestAlertException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -87,4 +88,22 @@ public class BookServiceImpl implements BookService { log.debug("Request to delete Book : {}", id); bookRepository.deleteById(id); } + + @Override + public Optional purchase(Long id) { + Optional bookDTO = findOne(id); + if(bookDTO.isPresent()) { + int quantity = bookDTO.get().getQuantity(); + if(quantity > 0) { + bookDTO.get().setQuantity(quantity - 1); + Book book = bookMapper.toEntity(bookDTO.get()); + book = bookRepository.save(book); + return bookDTO; + } + else { + throw new BadRequestAlertException("Book is not in stock", "book", "notinstock"); + } + } + return Optional.empty(); + } } diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java index efcc2c3495..0360ea05ed 100644 --- a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/web/rest/BookResource.java @@ -109,4 +109,10 @@ public class BookResource { bookService.delete(id); return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build(); } + + @GetMapping("/books/purchase/{id}") + public ResponseEntity purchase(@PathVariable Long id) { + Optional bookDTO = bookService.purchase(id); + return ResponseUtil.wrapOrNotFound(bookDTO); + } } diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.html b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.html index 0aef73282a..4a3c20e841 100644 --- a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.html +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.html @@ -38,6 +38,12 @@ class="btn btn-primary">   Edit + + diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.ts index 50a6bec9ad..6b84c0ba73 100644 --- a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.ts +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book-detail.component.ts @@ -2,6 +2,8 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { IBook } from 'app/shared/model/book.model'; +import { BookService } from 'app/entities/book/book.service'; +import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; @Component({ selector: 'jhi-book-detail', @@ -10,7 +12,7 @@ import { IBook } from 'app/shared/model/book.model'; export class BookDetailComponent implements OnInit { book: IBook; - constructor(protected activatedRoute: ActivatedRoute) {} + constructor(protected activatedRoute: ActivatedRoute, protected bookService: BookService) {} ngOnInit() { this.activatedRoute.data.subscribe(({ book }) => { @@ -21,4 +23,14 @@ export class BookDetailComponent implements OnInit { previousState() { window.history.back(); } + + purchase(id: number) { + console.log('Purchasing book ' + id); + this.bookService.purchase(id).subscribe( + (res: HttpResponse) => { + this.book = res.body; + }, + (res: HttpErrorResponse) => console.log(res.message) + ); + } } diff --git a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.service.ts b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.service.ts index 3ff649d25d..bff511f7e6 100644 --- a/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.service.ts +++ b/jhipster-5/bookstore-monolith/src/main/webapp/app/entities/book/book.service.ts @@ -38,6 +38,13 @@ export class BookService { .pipe(map((res: EntityResponseType) => this.convertDateFromServer(res))); } + purchase(id: number): Observable { + console.log('Calling /api/books/purchase/ ' + id); + return this.http + .get(`${this.resourceUrl}/purchase/${id}`, { observe: 'response' }) + .pipe(map((res: EntityResponseType) => this.convertDateFromServer(res))); + } + query(req?: any): Observable { const options = createRequestOption(req); return this.http From 1f857d5ad515859185292779fe37436e3e07fb31 Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Wed, 20 Mar 2019 16:00:42 +0000 Subject: [PATCH 421/496] BAEL-2522 - Tabs problem. Identation. --- java-dates-2/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-dates-2/pom.xml b/java-dates-2/pom.xml index 93216e3ffa..c2464ed47f 100644 --- a/java-dates-2/pom.xml +++ b/java-dates-2/pom.xml @@ -49,7 +49,7 @@ 3.6.1 - 1.9 + 1.9 1.9 From 66f20f14419d1201ce39e4c86a0eca502d5f110b Mon Sep 17 00:00:00 2001 From: Seun Matt Date: Wed, 20 Mar 2019 17:05:30 +0100 Subject: [PATCH 422/496] added example code for BAEL-2083 (#6486) * added example code for BAEL-2083 * updated example code for BAEL-2083 --- persistence-modules/hibernate5/pom.xml | 7 ++- .../com/baeldung/hibernate/HibernateUtil.java | 1 + .../com/baeldung/hibernate/pojo/Post.java | 59 +++++++++++++++++++ .../hibernate/transaction/PostService.java | 29 +++++++++ .../hibernate/CustomClassIntegrationTest.java | 2 + .../TransactionIntegrationTest.java | 57 ++++++++++++++++++ 6 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Post.java create mode 100644 persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/transaction/PostService.java create mode 100644 persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/transaction/TransactionIntegrationTest.java diff --git a/persistence-modules/hibernate5/pom.xml b/persistence-modules/hibernate5/pom.xml index a09669c8b5..c7f08e50d5 100644 --- a/persistence-modules/hibernate5/pom.xml +++ b/persistence-modules/hibernate5/pom.xml @@ -83,13 +83,18 @@ jmh-generator-annprocess ${openjdk-jmh.version} + + javax.xml.bind + jaxb-api + 2.3.0 + hibernate5 - src/main/resources + src/test/resources true diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java index ea0af97d5a..48c9b9d5c2 100644 --- a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/HibernateUtil.java @@ -113,6 +113,7 @@ public class HibernateUtil { metadataSources.addAnnotatedClass(OptimisticLockingCourse.class); metadataSources.addAnnotatedClass(OptimisticLockingStudent.class); metadataSources.addAnnotatedClass(OfficeEmployee.class); + metadataSources.addAnnotatedClass(Post.class); Metadata metadata = metadataSources.getMetadataBuilder() .applyBasicType(LocalDateStringType.INSTANCE) diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Post.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Post.java new file mode 100644 index 0000000000..25e51e35d0 --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/Post.java @@ -0,0 +1,59 @@ +package com.baeldung.hibernate.pojo; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "posts") +public class Post { + + @Id + @GeneratedValue + private int id; + + private String title; + + private String body; + + public Post() { } + + public Post(String title, String body) { + this.title = title; + this.body = body; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + @Override + public String toString() { + return "Post{" + + "id=" + id + + ", title='" + title + '\'' + + ", body='" + body + '\'' + + '}'; + } +} diff --git a/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/transaction/PostService.java b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/transaction/PostService.java new file mode 100644 index 0000000000..5a4eb20079 --- /dev/null +++ b/persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/transaction/PostService.java @@ -0,0 +1,29 @@ +package com.baeldung.hibernate.transaction; + +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.query.Query; + +public class PostService { + + + private Session session; + + public PostService(Session session) { + this.session = session; + } + + + public void updatePost(String title, String body, int id) { + Transaction txn = session.beginTransaction(); + Query updateQuery = session.createQuery("UPDATE Post p SET p.title = ?1, p.body = ?2 WHERE p.id = ?3"); + updateQuery.setParameter(1, title); + updateQuery.setParameter(2, body); + updateQuery.setParameter(3, id); + updateQuery.executeUpdate(); + txn.commit(); + } + + + +} diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/CustomClassIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/CustomClassIntegrationTest.java index 29ae55b773..e64e836924 100644 --- a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/CustomClassIntegrationTest.java +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/CustomClassIntegrationTest.java @@ -74,4 +74,6 @@ public class CustomClassIntegrationTest { assertEquals("John Smith", result.getEmployeeName()); assertEquals("Sales", result.getDepartmentName()); } + + } diff --git a/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/transaction/TransactionIntegrationTest.java b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/transaction/TransactionIntegrationTest.java new file mode 100644 index 0000000000..246a7d59f9 --- /dev/null +++ b/persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/transaction/TransactionIntegrationTest.java @@ -0,0 +1,57 @@ +package com.baeldung.hibernate.transaction; + +import com.baeldung.hibernate.HibernateUtil; +import com.baeldung.hibernate.pojo.Post; +import com.baeldung.hibernate.transaction.PostService; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; + +import static org.junit.Assert.assertEquals; + +public class TransactionIntegrationTest { + + private static PostService postService; + private static Session session; + private static Logger logger = LoggerFactory.getLogger(TransactionIntegrationTest.class); + + @BeforeClass + public static void init() throws IOException { + Properties properties = new Properties(); + properties.setProperty("hibernate.connection.driver_class", "org.h2.Driver"); + properties.setProperty("hibernate.connection.url", "jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1"); + properties.setProperty("hibernate.connection.username", "sa"); + properties.setProperty("hibernate.show_sql", "true"); + properties.setProperty("jdbc.password", ""); + properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); + properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); + SessionFactory sessionFactory = HibernateUtil.getSessionFactoryByProperties(properties); + session = sessionFactory.openSession(); + postService = new PostService(session); + } + + @Test + public void givenTitleAndBody_whenRepositoryUpdatePost_thenUpdatePost() { + + Post post = new Post("This is a title", "This is a sample post"); + session.persist(post); + + String title = "[UPDATE] Java HowTos"; + String body = "This is an updated posts on Java how-tos"; + postService.updatePost(title, body, post.getId()); + + session.refresh(post); + + assertEquals(post.getTitle(), title); + assertEquals(post.getBody(), body); + } + + +} From 284542701f10101e660198c74477158d1e7b5a53 Mon Sep 17 00:00:00 2001 From: "anilkivilcim.eray" Date: Wed, 20 Mar 2019 23:21:11 +0300 Subject: [PATCH 423/496] BAEL-2762 Fix tests in spring-boot-security module --- .../basic_auth/config/BasicAuthConfiguration.java | 9 +++++++-- .../config/AuthorizationServerConfig.java | 4 ++-- .../config/WebSecurityConfiguration.java | 15 +++++++++++++++ .../config/SpringBootSecurityTagLibsConfig.java | 2 +- .../BasicAuthConfigurationIntegrationTest.java | 5 ++--- 5 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2server/config/WebSecurityConfiguration.java diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java index 993c573fb0..a8a561a567 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java @@ -5,6 +5,8 @@ import org.springframework.security.config.annotation.authentication.builders.Au import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @@ -12,14 +14,17 @@ public class BasicAuthConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { + PasswordEncoder encoder = + PasswordEncoderFactories.createDelegatingPasswordEncoder(); + auth .inMemoryAuthentication() .withUser("user") - .password("password") + .password(encoder.encode("password")) .roles("USER") .and() .withUser("admin") - .password("admin") + .password("{noop}admin") .roles("USER", "ADMIN"); } diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2server/config/AuthorizationServerConfig.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2server/config/AuthorizationServerConfig.java index b403feb5c1..4686100638 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2server/config/AuthorizationServerConfig.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2server/config/AuthorizationServerConfig.java @@ -25,13 +25,13 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap clients .inMemory() .withClient("baeldung") - .secret("baeldung") + .secret("{noop}baeldung") .authorizedGrantTypes("client_credentials", "password", "authorization_code") .scopes("openid", "read") .autoApprove(true) .and() .withClient("baeldung-admin") - .secret("baeldung") + .secret("{noop}baeldung") .authorizedGrantTypes("authorization_code", "client_credentials", "refresh_token") .scopes("read", "write") .autoApprove(true); diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2server/config/WebSecurityConfiguration.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2server/config/WebSecurityConfiguration.java new file mode 100644 index 0000000000..f2540c01b8 --- /dev/null +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/oauth2server/config/WebSecurityConfiguration.java @@ -0,0 +1,15 @@ +package com.baeldung.springbootsecurity.oauth2server.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Bean + public AuthenticationManager customAuthenticationManager() throws Exception { + return authenticationManager(); + } +} diff --git a/spring-boot-security/src/main/java/com/baeldung/springsecuritytaglibs/config/SpringBootSecurityTagLibsConfig.java b/spring-boot-security/src/main/java/com/baeldung/springsecuritytaglibs/config/SpringBootSecurityTagLibsConfig.java index 665dd0bce9..59ae2885ad 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springsecuritytaglibs/config/SpringBootSecurityTagLibsConfig.java +++ b/spring-boot-security/src/main/java/com/baeldung/springsecuritytaglibs/config/SpringBootSecurityTagLibsConfig.java @@ -14,7 +14,7 @@ public class SpringBootSecurityTagLibsConfig extends WebSecurityConfigurerAdapte protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("testUser") - .password("password") + .password("{noop}password") .roles("ADMIN"); } diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java index 98e76e7bab..a5c2d11a01 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java @@ -1,5 +1,6 @@ package com.baeldung.springbootsecurity.basic_auth; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,8 +50,6 @@ public class BasicAuthConfigurationIntegrationTest { ResponseEntity response = restTemplate.getForEntity(base.toString(), String.class); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); - assertTrue(response - .getBody() - .contains("Unauthorized")); + Assert.assertNull(response.getBody()); } } From 117e4038b9a4503b600fa4ef5b2b618c1b756867 Mon Sep 17 00:00:00 2001 From: "sumit.sg34" Date: Thu, 21 Mar 2019 10:24:37 +0530 Subject: [PATCH 424/496] BAEL-2827 code added for deleteby methods --- .../spring-data-jpa-2/README.md | 34 ++++++++++ persistence-modules/spring-data-jpa-2/pom.xml | 30 +++++++++ .../main/java/com/baeldung/Application.java | 13 ++++ .../main/java/com/baeldung/entity/Fruit.java | 38 +++++++++++ .../baeldung/repository/FruitRepository.java | 20 ++++++ .../src/main/resources/application.properties | 1 + .../FruitRepositoryIntegrationTest.java | 65 +++++++++++++++++++ .../src/test/resources/test-fruit-data.sql | 4 ++ 8 files changed, 205 insertions(+) create mode 100644 persistence-modules/spring-data-jpa-2/README.md create mode 100644 persistence-modules/spring-data-jpa-2/pom.xml create mode 100644 persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/Application.java create mode 100644 persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Fruit.java create mode 100644 persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/FruitRepository.java create mode 100644 persistence-modules/spring-data-jpa-2/src/main/resources/application.properties create mode 100644 persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-2/src/test/resources/test-fruit-data.sql diff --git a/persistence-modules/spring-data-jpa-2/README.md b/persistence-modules/spring-data-jpa-2/README.md new file mode 100644 index 0000000000..8dff49640e --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/README.md @@ -0,0 +1,34 @@ +========= + +## Spring Data JPA Example Project + +### Relevant Articles: +- [Spring JPA – Multiple Databases](http://www.baeldung.com/spring-data-jpa-multiple-databases) +- [Spring Data JPA – Adding a Method in All Repositories](http://www.baeldung.com/spring-data-jpa-method-in-all-repositories) +- [Advanced Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging-advanced) +- [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query) +- [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations) +- [Spring Data Java 8 Support](http://www.baeldung.com/spring-data-java-8) +- [A Simple Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging) +- [Spring Data Composable Repositories](https://www.baeldung.com/spring-data-composable-repositories) +- [Auditing with JPA, Hibernate, and Spring Data JPA](https://www.baeldung.com/database-auditing-jpa) +- [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date) +- [DDD Aggregates and @DomainEvents](https://www.baeldung.com/spring-data-ddd) +- [Spring Data – CrudRepository save() Method](https://www.baeldung.com/spring-data-crud-repository-save) +- [Limiting Query Results with JPA and Spring Data JPA](https://www.baeldung.com/jpa-limit-query-results) +- [Sorting Query Results with Spring Data](https://www.baeldung.com/spring-data-sorting) +- [INSERT Statement in JPA](https://www.baeldung.com/jpa-insert) +- [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) +- [Spring Data JPA Query by Example](https://www.baeldung.com/spring-data-query-by-example) +- [DB Integration Tests with Spring Boot and Testcontainers](https://www.baeldung.com/spring-boot-testcontainers-integration-test) +- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) + +### Eclipse Config +After importing the project into Eclipse, you may see the following error: +"No persistence xml file found in project" + +This can be ignored: +- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project" +Or: +- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator + diff --git a/persistence-modules/spring-data-jpa-2/pom.xml b/persistence-modules/spring-data-jpa-2/pom.xml new file mode 100644 index 0000000000..8e46112659 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + com.baeldung + spring-data-jpa-2 + spring-data-jpa + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.h2database + h2 + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/Application.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/Application.java new file mode 100644 index 0000000000..3ea3d113da --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/Application.java @@ -0,0 +1,13 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Fruit.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Fruit.java new file mode 100644 index 0000000000..f82022e67e --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Fruit.java @@ -0,0 +1,38 @@ +package com.baeldung.entity; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class Fruit { + + @Id + private long id; + private String name; + private String color; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/FruitRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/FruitRepository.java new file mode 100644 index 0000000000..b3dcc0542b --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/FruitRepository.java @@ -0,0 +1,20 @@ +package com.baeldung.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.baeldung.entity.Fruit; + +@Repository +public interface FruitRepository extends JpaRepository { + + Long deleteByName(String name); + + List deleteByColor(String color); + + Long removeByName(String name); + + List removeByColor(String color); +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-2/src/main/resources/application.properties new file mode 100644 index 0000000000..72fc330767 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.jpa.show-sql=true \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java new file mode 100644 index 0000000000..45c106337f --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java @@ -0,0 +1,65 @@ +package com.baeldung.repository; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.entity.Fruit; + +@RunWith(SpringRunner.class) +@SpringBootTest +class FruitRepositoryIntegrationTest { + + @Autowired + private FruitRepository fruitRepository; + + @Transactional + @Test + @Sql(scripts = { "/test-fruit-data.sql" }) + public void givenFruits_WhenDeletedByColor_DeletedFruitShouldReturn() { + + List fruits = fruitRepository.deleteByColor("green"); + + assertEquals("number of fruits are not matching", 2, fruits.size()); + fruits.forEach(fruit -> assertEquals("Its not a green fruit", "green", fruit.getColor())); + } + + @Transactional + @Test + @Sql(scripts = { "/test-fruit-data.sql" }) + public void givenFruits_WhenDeletedByName_DeletedFruitCountShouldReturn() { + + Long deletedFruitCount = fruitRepository.deleteByName("apple"); + + assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue()); + } + + @Transactional + @Test + @Sql(scripts = { "/test-fruit-data.sql" }) + public void givenFruits_WhenRemovedByColor_DeletedFruitShouldReturn() { + + List fruits = fruitRepository.removeByColor("green"); + + assertEquals("number of fruits are not matching", 2, fruits.size()); + fruits.forEach(fruit -> assertEquals("Its not a green fruit", "green", fruit.getColor())); + } + + @Transactional + @Test + @Sql(scripts = { "/test-fruit-data.sql" }) + public void givenFruits_WhenRemovedByName_DeletedFruitCountShouldReturn() { + + Long deletedFruitCount = fruitRepository.removeByName("apple"); + + assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue()); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/test-fruit-data.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/test-fruit-data.sql new file mode 100644 index 0000000000..ce2189121f --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/resources/test-fruit-data.sql @@ -0,0 +1,4 @@ +insert into fruit(id,name,color) values (1,'apple','red'); +insert into fruit(id,name,color) values (2,'custard apple','green'); +insert into fruit(id,name,color) values (3,'mango','yellow'); +insert into fruit(id,name,color) values (4,'guava','green'); \ No newline at end of file From 3580562910c85e119b3f7c03cabd35e89635c367 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 21 Mar 2019 14:38:03 +0800 Subject: [PATCH 425/496] Update README.md --- jackson/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/jackson/README.md b/jackson/README.md index 15af88fe26..e9cf6f212c 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -39,5 +39,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Convert XML to JSON Using Jackson](https://www.baeldung.com/jackson-convert-xml-json) - [Deserialize Immutable Objects with Jackson](https://www.baeldung.com/jackson-deserialize-immutable-objects) - [Mapping a Dynamic JSON Object with Jackson](https://www.baeldung.com/jackson-mapping-dynamic-object) -- [Mapping Multiple JSON Fields to a Single Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) From 5c9a3be5324e2347f4bdb7579c1e2afec797ef0f Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 21 Mar 2019 14:40:59 +0800 Subject: [PATCH 426/496] Update README.md --- core-java-9/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core-java-9/README.md b/core-java-9/README.md index 9ce419b054..a423f0cb14 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -28,3 +28,5 @@ - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) - [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation) - [Java 9 Process API Improvements](https://www.baeldung.com/java-9-process-api) +- [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) + From c4cc859b672d695c70d412d0f3652043f311bb29 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 21 Mar 2019 14:46:43 +0800 Subject: [PATCH 427/496] Update README.md --- core-java-collections/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-collections/README.md b/core-java-collections/README.md index 80d4385c45..1e504ded65 100644 --- a/core-java-collections/README.md +++ b/core-java-collections/README.md @@ -33,3 +33,4 @@ - [Differences Between HashMap and Hashtable](https://www.baeldung.com/hashmap-hashtable-differences) - [Java ArrayList vs Vector](https://www.baeldung.com/java-arraylist-vs-vector) - [Defining a Char Stack in Java](https://www.baeldung.com/java-char-stack) +- [Time Comparison of Arrays.sort(Object[]) and Arrays.sort(int[])](https://www.baeldung.com/arrays-sortobject-vs-sortint) From 26f8de58348f41d1a8c668edd70cf83def25bffd Mon Sep 17 00:00:00 2001 From: "anilkivilcim.eray" Date: Thu, 21 Mar 2019 09:54:15 +0300 Subject: [PATCH 428/496] BAEL-2762 renaming HomeControllerIntegrationTest to HomeControllerUnitTest --- ...ntrollerIntegrationTest.java => HomeControllerUnitTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/{HomeControllerIntegrationTest.java => HomeControllerUnitTest.java} (98%) diff --git a/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java similarity index 98% rename from spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java rename to spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java index 654e7925b9..0585c06a59 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerIntegrationTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springsecuritytaglibs/HomeControllerUnitTest.java @@ -13,7 +13,7 @@ import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = SpringBootSecurityTagLibsApplication.class) -public class HomeControllerIntegrationTest { +public class HomeControllerUnitTest { @Autowired private TestRestTemplate restTemplate; From e4725557a2b49991d37f31245c4e00835d7906c1 Mon Sep 17 00:00:00 2001 From: kwoyke Date: Thu, 21 Mar 2019 16:43:08 +0100 Subject: [PATCH 429/496] BAEL-2777 Add a new section in Sorting with Lambda article (#6546) --- .../com/baeldung/java8/Java8SortUnitTest.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java index 71ec5b147f..57d9d8347b 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java @@ -124,11 +124,44 @@ public class Java8SortUnitTest { @Test public final void givenStreamCustomOrdering_whenSortingEntitiesByName_thenCorrectlySorted() { - final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); final Comparator nameComparator = (h1, h2) -> h1.getName().compareTo(h2.getName()); final List sortedHumans = humans.stream().sorted(nameComparator).collect(Collectors.toList()); Assert.assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12))); } + + @Test + public final void givenStreamComparatorOrdering_whenSortingEntitiesByName_thenCorrectlySorted() { + final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); + + final List sortedHumans = humans.stream().sorted(Comparator.comparing(Human::getName)).collect(Collectors.toList()); + Assert.assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12))); + } + + @Test + public final void givenStreamNaturalOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() { + final List letters = Lists.newArrayList("B", "A", "C"); + + final List reverseSortedLetters = letters.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()); + Assert.assertThat(reverseSortedLetters.get(0), equalTo("C")); + } + + @Test + public final void givenStreamCustomOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() { + final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); + final Comparator reverseNameComparator = (h1, h2) -> h2.getName().compareTo(h1.getName()); + + final List reverseSortedHumans = humans.stream().sorted(reverseNameComparator).collect(Collectors.toList()); + Assert.assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10))); + } + + @Test + public final void givenStreamComparatorOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() { + final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12)); + + final List reverseSortedHumans = humans.stream().sorted(Comparator.comparing(Human::getName, Comparator.reverseOrder())).collect(Collectors.toList()); + Assert.assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10))); + } + } From 18eb32a7dbf2405b30c59cd0ce36b171b6c74b6f Mon Sep 17 00:00:00 2001 From: Ali Dehghani Date: Fri, 22 Mar 2019 03:46:02 +0430 Subject: [PATCH 430/496] Introducing the core-java-12 module. It's ignored just like other 9+ versions. --- core-java-12/pom.xml | 48 ++++++++++++ .../collectors/CollectorsUnitTest.java | 77 +++++++++++++++++++ pom.xml | 1 + 3 files changed, 126 insertions(+) create mode 100644 core-java-12/pom.xml create mode 100644 core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java diff --git a/core-java-12/pom.xml b/core-java-12/pom.xml new file mode 100644 index 0000000000..729b29381b --- /dev/null +++ b/core-java-12/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + com.baeldung + core-java-12 + 0.1.0-SNAPSHOT + core-java-12 + jar + http://maven.apache.org + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source.version} + ${maven.compiler.target.version} + + + + + + + 12 + 12 + 3.6.1 + + + \ No newline at end of file diff --git a/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java b/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java new file mode 100644 index 0000000000..68915b504d --- /dev/null +++ b/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java @@ -0,0 +1,77 @@ +package com.baeldung.collectors; + +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +import org.junit.Test; + +import static java.util.stream.Collectors.maxBy; +import static java.util.stream.Collectors.minBy; +import static java.util.stream.Collectors.teeing; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Unit tests for collectors additions in Java 12. + */ +public class CollectorsUnitTest { + + @Test + public void whenTeeing_ItShouldCombineTheResultsAsExpected() { + List numbers = Arrays.asList(42, 4, 2, 24); + Range range = numbers.stream() + .collect(teeing( + minBy(Integer::compareTo), + maxBy(Integer::compareTo), + (min, max) -> new Range(min.orElse(null), max.orElse(null)) + )); + + assertThat(range).isEqualTo(new Range(2, 42)); + } + + /** + * Represents a closed range of numbers between {@link #min} and + * {@link #max}, both inclusive. + */ + private static class Range { + + private final Integer min; + + private final Integer max; + + Range(Integer min, Integer max) { + this.min = min; + this.max = max; + } + + Integer getMin() { + return min; + } + + Integer getMax() { + return max; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Range range = (Range) o; + return Objects.equals(getMin(), range.getMin()) && + Objects.equals(getMax(), range.getMax()); + } + + @Override + public int hashCode() { + return Objects.hash(getMin(), getMax()); + } + + @Override + public String toString() { + return "Range{" + + "min=" + min + + ", max=" + max + + '}'; + } + } +} diff --git a/pom.xml b/pom.xml index bf225d82f0..d97c30ad64 100644 --- a/pom.xml +++ b/pom.xml @@ -377,6 +377,7 @@ core-groovy + core-java-8 From 4b962b45e823386c02f835e01bb165587c4188cc Mon Sep 17 00:00:00 2001 From: eelhazati <35301254+eelhazati@users.noreply.github.com> Date: Fri, 22 Mar 2019 11:44:17 +0000 Subject: [PATCH 431/496] Update application.properties --- .../src/main/resources/application.properties | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties index de8e1a7b9f..4b9d8106eb 100644 --- a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties @@ -1,23 +1,10 @@ -# SECURITY OAUTH2 CLIENT (OAuth2ClientProperties) -#spring.security.oauth2.client.provider.*= # OAuth provider details. -#spring.security.oauth2.client.registration.*= # OAuth client registrations. - server.port=8081 -#server.servlet.context-path=/uaa-client-webapp -uaa.url=http://localhost:8080/uaa resource.server.url=http://localhost:8082 -spring.security.oauth2.client.registration.uaa.client-name=UAA OAuth2 Client -spring.security.oauth2.client.registration.uaa.client-id=client1 -spring.security.oauth2.client.registration.uaa.client-secret=client1 -spring.security.oauth2.client.registration.uaa.authorization-grant-type=authorization_code +spring.security.oauth2.client.registration.uaa.client-id=webappclient +spring.security.oauth2.client.registration.uaa.client-secret=webappclientsecret spring.security.oauth2.client.registration.uaa.scope=resource.read,resource.write,openid,profile -spring.security.oauth2.client.registration.uaa.redirect-uri=http://localhost:8081/login/oauth2/code/uaa -#spring.security.oauth2.client.registration.uaa.redirect-uri=http://localhost:8081/** -spring.security.oauth2.client.provider.uaa.token-uri=${uaa.url}/oauth/token -spring.security.oauth2.client.provider.uaa.authorization-uri=${uaa.url}/oauth/authorize -spring.security.oauth2.client.provider.uaa.jwk-set-uri=${uaa.url}/token_keys -spring.security.oauth2.client.provider.uaa.user-info-uri=${uaa.url}/userinfo -spring.security.oauth2.client.provider.uaa.user-name-attribute=user_name +spring.security.oauth2.client.provider.uaa.issuer-uri=http://localhost:8080/uaa/oauth/token + From c6a54656f22df47565b5cc8130435738383ca534 Mon Sep 17 00:00:00 2001 From: eelhazati <35301254+eelhazati@users.noreply.github.com> Date: Fri, 22 Mar 2019 11:45:49 +0000 Subject: [PATCH 432/496] Update application.properties --- .../src/main/resources/application.properties | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties index ba9b95e0d4..a6e846a00f 100644 --- a/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties +++ b/cloud-foundry-uaa/cf-uaa-oauth2-resource-server/src/main/resources/application.properties @@ -1,16 +1,3 @@ server.port=8082 -uaa.url=http://localhost:8080/uaa - -#approch1 -spring.security.oauth2.resourceserver.jwt.issuer-uri=${uaa.url}/oauth/token - -#approch2 -#spring.security.oauth2.resourceserver.jwt.jwk-set-uri=${uaa.url}/token_key - -# SECURITY OAUTH2 CLIENT (OAuth2ClientProperties) -#security.oauth2.client.client-id=client1 -#security.oauth2.client.client-secret=client1 - -#security.oauth2.resource.jwt.key-uri=${uaa.url}/token_key -#security.oauth2.resource.token-info-uri=${uaa.url}/oauth/check_token +spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/uaa/oauth/token From 700a9530d78cb33eb8e475a7968a5ee7e7882ad2 Mon Sep 17 00:00:00 2001 From: eelhazati <35301254+eelhazati@users.noreply.github.com> Date: Fri, 22 Mar 2019 11:57:45 +0000 Subject: [PATCH 433/496] Update uaa.yml --- cloud-foundry-uaa/cf-uaa-config/uaa.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/cloud-foundry-uaa/cf-uaa-config/uaa.yml b/cloud-foundry-uaa/cf-uaa-config/uaa.yml index b782c2b681..ebaa99fb6c 100644 --- a/cloud-foundry-uaa/cf-uaa-config/uaa.yml +++ b/cloud-foundry-uaa/cf-uaa-config/uaa.yml @@ -1,12 +1,7 @@ issuer: uri: http://localhost:8080/uaa -spring_profiles: postgresql,default - -database.driverClassName: org.postgresql.Driver -database.url: jdbc:postgresql:uaadb2 -database.username: postgres -database.password: postgres +spring_profiles: default,hsqldb encryption: active_key_label: CHANGE-THIS-KEY From 640af4ccbea16195e1cc8b0620392c328d2e2c83 Mon Sep 17 00:00:00 2001 From: eelhazati <35301254+eelhazati@users.noreply.github.com> Date: Fri, 22 Mar 2019 12:49:37 +0000 Subject: [PATCH 434/496] Update application.properties --- .../src/main/resources/application.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties index 4b9d8106eb..8e8797ce54 100644 --- a/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties +++ b/cloud-foundry-uaa/cf-uaa-oauth2-client/src/main/resources/application.properties @@ -2,6 +2,7 @@ server.port=8081 resource.server.url=http://localhost:8082 +spring.security.oauth2.client.registration.uaa.client-name=Web App Client spring.security.oauth2.client.registration.uaa.client-id=webappclient spring.security.oauth2.client.registration.uaa.client-secret=webappclientsecret spring.security.oauth2.client.registration.uaa.scope=resource.read,resource.write,openid,profile From 4151e55d3b32e963dbf67b489a2d827fe8587d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Frankowski?= Date: Mon, 11 Mar 2019 18:17:36 +0100 Subject: [PATCH 435/496] [BAEL-2664] Groovy collections find --- .../main/groovy/com/baeldung/Person.groovy | 37 ++++++++++ .../groovy/com/baeldung/lists/ListTest.groovy | 8 +- .../com/baeldung/lists/ListUnitTest.groovy | 58 +++++++++++++++ .../com/baeldung/map/MapUnitTest.groovy | 73 ++++++++++++++++++- .../com/baeldung/set/SetUnitTest.groovy | 16 ++++ 5 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 core-groovy/src/main/groovy/com/baeldung/Person.groovy create mode 100644 core-groovy/src/test/groovy/com/baeldung/lists/ListUnitTest.groovy create mode 100644 core-groovy/src/test/groovy/com/baeldung/set/SetUnitTest.groovy diff --git a/core-groovy/src/main/groovy/com/baeldung/Person.groovy b/core-groovy/src/main/groovy/com/baeldung/Person.groovy new file mode 100644 index 0000000000..6a009aeee0 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/Person.groovy @@ -0,0 +1,37 @@ +package com.baeldung + +class Person { + private String firstname + private String lastname + private Integer age + + Person(String firstname, String lastname, Integer age) { + this.firstname = firstname + this.lastname = lastname + this.age = age + } + + String getFirstname() { + return firstname + } + + void setFirstname(String firstname) { + this.firstname = firstname + } + + String getLastname() { + return lastname + } + + void setLastname(String lastname) { + this.lastname = lastname + } + + Integer getAge() { + return age + } + + void setAge(Integer age) { + this.age = age + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy index f682503ed4..7771028132 100644 --- a/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/lists/ListTest.groovy @@ -129,13 +129,13 @@ class ListTest{ assertTrue(filterList.findAll{it > 3} == [4, 5, 6, 76]) assertTrue(filterList.findAll{ it instanceof Number} == [2, 1, 3, 4, 5, 6, 76]) - + assertTrue(filterList.grep( Number )== [2, 1, 3, 4, 5, 6, 76]) - + assertTrue(filterList.grep{ it> 6 }== [76]) def conditionList = [2, 1, 3, 4, 5, 6, 76] - + assertFalse(conditionList.every{ it < 6}) assertTrue(conditionList.any{ it%2 == 0}) @@ -165,7 +165,7 @@ class ListTest{ def strList = ["na", "ppp", "as"] assertTrue(strList.max() == "ppp") - + Comparator minc = {a,b -> a == b? 0: a < b? -1 : 1} def numberList = [3, 2, 0, 7] assertTrue(numberList.min(minc) == 0) diff --git a/core-groovy/src/test/groovy/com/baeldung/lists/ListUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/lists/ListUnitTest.groovy new file mode 100644 index 0000000000..9617c099ce --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/lists/ListUnitTest.groovy @@ -0,0 +1,58 @@ +package com.baeldung.lists + +import com.baeldung.Person +import org.junit.Test + +import static org.junit.Assert.* + +class ListUnitTest { + + private final personList = [ + new Person("Regina", "Fitzpatrick", 25), + new Person("Abagail", "Ballard", 26), + new Person("Lucian", "Walter", 30), + ] + + @Test + void whenListContainsElement_thenCheckReturnsTrue() { + def list = ['a', 'b', 'c'] + + assertTrue(list.indexOf('a') > -1) + assertTrue(list.contains('a')) + } + + @Test + void whenListContainsElement_thenCheckWithMembershipOperatorReturnsTrue() { + def list = ['a', 'b', 'c'] + + assertTrue('a' in list) + } + + @Test + void givenListOfPerson_whenUsingStreamMatching_thenShouldEvaluateList() { + assertTrue(personList.stream().anyMatch {it.age > 20}) + assertFalse(personList.stream().allMatch {it.age < 30}) + } + + @Test + void givenListOfPerson_whenUsingCollectionMatching_thenShouldEvaluateList() { + assertTrue(personList.any {it.age > 20}) + assertFalse(personList.every {it.age < 30}) + } + + @Test + void givenListOfPerson_whenUsingStreamFind_thenShouldReturnMatchingElements() { + assertTrue(personList.stream().filter {it.age > 20}.findAny().isPresent()) + assertFalse(personList.stream().filter {it.age > 30}.findAny().isPresent()) + assertTrue(personList.stream().filter {it.age > 20}.findAll().size() == 3) + assertTrue(personList.stream().filter {it.age > 30}.findAll().isEmpty()) + } + + @Test + void givenListOfPerson_whenUsingCollectionFind_thenShouldReturnMatchingElements() { + assertNotNull(personList.find {it.age > 20}) + assertNull(personList.find {it.age > 30}) + assertTrue(personList.findAll {it.age > 20}.size() == 3) + assertTrue(personList.findAll {it.age > 30}.isEmpty()) + } +} diff --git a/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy index 97ffc50c76..0d6bbed04b 100644 --- a/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy +++ b/core-groovy/src/test/groovy/com/baeldung/map/MapUnitTest.groovy @@ -1,10 +1,18 @@ package com.baeldung.map -import static org.junit.Assert.* +import com.baeldung.Person import org.junit.Test +import static org.junit.Assert.* + class MapUnitTest { + private final personMap = [ + Regina : new Person("Regina", "Fitzpatrick", 25), + Abagail: new Person("Abagail", "Ballard", 26), + Lucian : new Person("Lucian", "Walter", 30) + ] + @Test void whenUsingEach_thenMapIsIterated() { def map = [ @@ -63,7 +71,7 @@ class MapUnitTest { 'FF6347' : 'Tomato', 'FF4500' : 'Orange Red' ] - + map.eachWithIndex { key, val, index -> def indent = ((index == 0 || index % 2 == 0) ? " " : "") println "$indent Hex Code: $key = Color Name: $val" @@ -82,4 +90,65 @@ class MapUnitTest { println "Hex Code: $entry.key = Color Name: $entry.value" } } + + @Test + void whenMapContainsKeyElement_thenCheckReturnsTrue() { + def map = [a: 'd', b: 'e', c: 'f'] + + assertTrue(map.containsKey('a')) + assertFalse(map.containsKey('e')) + assertTrue(map.containsValue('e')) + } + + @Test + void whenMapContainsKeyElement_thenCheckByMembershipReturnsTrue() { + def map = [a: 'd', b: 'e', c: 'f'] + + assertTrue('a' in map) + assertFalse('f' in map) + } + + @Test + void whenMapContainsFalseBooleanValues_thenCheckReturnsFalse() { + def map = [a: true, b: false, c: null] + + assertTrue(map.containsKey('b')) + assertTrue('a' in map) + assertFalse('b' in map) + assertFalse('c' in map) + } + + @Test + void givenMapOfPerson_whenUsingStreamMatching_thenShouldEvaluateMap() { + assertTrue(personMap.keySet().stream().anyMatch {it == "Regina"}) + assertFalse(personMap.keySet().stream().allMatch {it == "Albert"}) + assertFalse(personMap.values().stream().allMatch {it.age < 30}) + assertTrue(personMap.entrySet().stream().anyMatch {it.key == "Abagail" && it.value.lastname == "Ballard"}) + } + + @Test + void givenMapOfPerson_whenUsingCollectionMatching_thenShouldEvaluateMap() { + assertTrue(personMap.keySet().any {it == "Regina"}) + assertFalse(personMap.keySet().every {it == "Albert"}) + assertFalse(personMap.values().every {it.age < 30}) + assertTrue(personMap.any {firstname, person -> firstname == "Abagail" && person.lastname == "Ballard"}) + } + + @Test + void givenMapOfPerson_whenUsingCollectionFind_thenShouldReturnElements() { + assertNotNull(personMap.find {it.key == "Abagail" && it.value.lastname == "Ballard"}) + assertTrue(personMap.findAll {it.value.age > 20}.size() == 3) + } + + @Test + void givenMapOfPerson_whenUsingStreamFind_thenShouldReturnElements() { + assertTrue( + personMap.entrySet().stream() + .filter {it.key == "Abagail" && it.value.lastname == "Ballard"} + .findAny().isPresent()) + assertTrue( + personMap.entrySet().stream() + .filter {it.value.age > 20} + .findAll().size() == 3) + } } diff --git a/core-groovy/src/test/groovy/com/baeldung/set/SetUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/set/SetUnitTest.groovy new file mode 100644 index 0000000000..1248c9ac91 --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/set/SetUnitTest.groovy @@ -0,0 +1,16 @@ +package com.baeldung.set + +import org.junit.Test + +import static org.junit.Assert.assertTrue + +class SetUnitTest { + + @Test + void whenSetContainsElement_thenCheckReturnsTrue() { + def set = ['a', 'b', 'c'] as Set + + assertTrue(set.contains('a')) + assertTrue('a' in set) + } +} \ No newline at end of file From 2b8c73c3767691b7e226de82f931cf3a57449a90 Mon Sep 17 00:00:00 2001 From: "sumit.sg34" Date: Fri, 22 Mar 2019 23:20:12 +0530 Subject: [PATCH 436/496] BAEL-2827 added one example for @query --- .../com/baeldung/repository/FruitRepository.java | 7 +++++++ .../repository/FruitRepositoryIntegrationTest.java | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/FruitRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/FruitRepository.java index b3dcc0542b..9f92909b66 100644 --- a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/FruitRepository.java +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/FruitRepository.java @@ -3,6 +3,9 @@ package com.baeldung.repository; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import com.baeldung.entity.Fruit; @@ -17,4 +20,8 @@ public interface FruitRepository extends JpaRepository { Long removeByName(String name); List removeByColor(String color); + + @Modifying + @Query("delete from Fruit f where f.name=:name or f.color=:color") + List deleteFruits(@Param("name") String name, @Param("color") String color); } diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java index 45c106337f..74188497ee 100644 --- a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java @@ -1,6 +1,7 @@ package com.baeldung.repository; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.List; @@ -62,4 +63,15 @@ class FruitRepositoryIntegrationTest { assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue()); } + + @Transactional + @Test + @Sql(scripts = { "/test-fruit-data.sql" }) + public void givenFruits_WhenDeletedByColorOrName_DeletedFruitShouldReturn() { + + List fruits = fruitRepository.deleteFruits("apple", "green"); + + assertEquals("number of fruits are not matching", 3, fruits.size()); + fruits.forEach(fruit -> assertTrue("Its not a green fruit or apple", ("green".equals(fruit.getColor())) || "apple".equals(fruit.getColor()))); + } } \ No newline at end of file From cc73a3051b80af57351cf072b9d61c6c6db0924e Mon Sep 17 00:00:00 2001 From: rahusriv Date: Sat, 23 Mar 2019 05:17:23 +0530 Subject: [PATCH 437/496] Rahul/socket/read/pr4 (#6575) * Making examples simple * Changing variable names * Modificatons in naming * Review changes --- .../java/com/baeldung/socket/read/Client.java | 30 ++++------- .../java/com/baeldung/socket/read/Server.java | 50 +++++++++---------- 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java b/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java index 08292237f2..5e2a84a767 100644 --- a/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java +++ b/core-java-networking/src/main/java/com/baeldung/socket/read/Client.java @@ -1,35 +1,27 @@ package com.baeldung.socket.read; -import java.net.*; +import java.net.*; +import java.nio.charset.StandardCharsets; import java.io.*; public class Client { - - //Initialize socket, input and output stream - private Socket socket = null; - private DataInputStream in = null; - private DataOutputStream out = null; public void runClient(String ip, int port) { try { - socket = new Socket(ip, port); + Socket socket = new Socket(ip, port); System.out.println("Connected to server ..."); - in = new DataInputStream(System.in); - out = new DataOutputStream(socket.getOutputStream()); - } catch(Exception e) { - e.printStackTrace(); - } - char type = 's'; // s for string - int length = 29; - String data = "This is a string of length 29"; - byte[] dataInBytes = data.getBytes(); - //Sending data in TLV format - try { + DataInputStream in = new DataInputStream(System.in); + DataOutputStream out = new DataOutputStream(socket.getOutputStream()); + + char type = 's'; // s for string + int length = 29; + String data = "This is a string of length 29"; + byte[] dataInBytes = data.getBytes(StandardCharsets.UTF_8); + //Sending data in TLV format out.writeChar(type); out.writeInt(length); out.write(dataInBytes); } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } diff --git a/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java b/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java index bdb3a4449f..2ab91c6cdc 100644 --- a/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java +++ b/core-java-networking/src/main/java/com/baeldung/socket/read/Server.java @@ -1,48 +1,46 @@ package com.baeldung.socket.read; -import java.net.*; +import java.net.*; +import java.nio.charset.StandardCharsets; import java.io.*; public class Server { - - //Socket and input stream - private Socket socket = null; - private ServerSocket server = null; - private DataInputStream in = null; public void runServer(int port) { //Start the server and wait for connection try { - server = new ServerSocket(port); + ServerSocket server = new ServerSocket(port); System.out.println("Server Started. Waiting for connection ..."); - socket = server.accept(); + Socket socket = server.accept(); System.out.println("Got connection from client."); //Get input stream from socket variable and convert the same to DataInputStream - in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); + DataInputStream in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); //Read type and length of data char dataType = in.readChar(); int length = in.readInt(); System.out.println("Type : "+dataType); System.out.println("Lenght :"+length); - //Read String data in bytes - byte[] messageByte = new byte[length]; - boolean end = false; - String dataString = ""; - int totalBytesRead = 0; - //We need to run while loop, to read all data in that stream - while(!end) { - int currentBytesRead = in.read(messageByte); - totalBytesRead = currentBytesRead + totalBytesRead; - if(totalBytesRead <= length) { - dataString += new String(messageByte,0,currentBytesRead); - } else { - dataString += new String(messageByte,0,length - totalBytesRead + currentBytesRead); - } - if(dataString.length()>=length) { - end = true; + if(dataType == 's') { + //Read String data in bytes + byte[] messageByte = new byte[length]; + boolean end = false; + StringBuilder dataString = new StringBuilder(length); + int totalBytesRead = 0; + //We need to run while loop, to read all data in that stream + while(!end) { + int currentBytesRead = in.read(messageByte); + totalBytesRead = currentBytesRead + totalBytesRead; + if(totalBytesRead <= length) { + dataString.append(new String(messageByte,0,currentBytesRead,StandardCharsets.UTF_8)); + } else { + dataString.append(new String(messageByte,0,length - totalBytesRead + currentBytesRead,StandardCharsets.UTF_8)); + } + if(dataString.length()>=length) { + end = true; + } } + System.out.println("Read "+length+" bytes of message from client. Message = "+dataString); } - System.out.println("Read "+length+" bytes of message from client. Message = "+dataString);; } catch (Exception e) { e.printStackTrace(); } From 5575383a0dd671ee20587ae049d23d89938454bd Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 23 Mar 2019 12:15:58 +0200 Subject: [PATCH 438/496] Update README.md --- .../spring-data-jpa-2/README.md | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/persistence-modules/spring-data-jpa-2/README.md b/persistence-modules/spring-data-jpa-2/README.md index 8dff49640e..295a434d17 100644 --- a/persistence-modules/spring-data-jpa-2/README.md +++ b/persistence-modules/spring-data-jpa-2/README.md @@ -3,32 +3,3 @@ ## Spring Data JPA Example Project ### Relevant Articles: -- [Spring JPA – Multiple Databases](http://www.baeldung.com/spring-data-jpa-multiple-databases) -- [Spring Data JPA – Adding a Method in All Repositories](http://www.baeldung.com/spring-data-jpa-method-in-all-repositories) -- [Advanced Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging-advanced) -- [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query) -- [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations) -- [Spring Data Java 8 Support](http://www.baeldung.com/spring-data-java-8) -- [A Simple Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging) -- [Spring Data Composable Repositories](https://www.baeldung.com/spring-data-composable-repositories) -- [Auditing with JPA, Hibernate, and Spring Data JPA](https://www.baeldung.com/database-auditing-jpa) -- [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date) -- [DDD Aggregates and @DomainEvents](https://www.baeldung.com/spring-data-ddd) -- [Spring Data – CrudRepository save() Method](https://www.baeldung.com/spring-data-crud-repository-save) -- [Limiting Query Results with JPA and Spring Data JPA](https://www.baeldung.com/jpa-limit-query-results) -- [Sorting Query Results with Spring Data](https://www.baeldung.com/spring-data-sorting) -- [INSERT Statement in JPA](https://www.baeldung.com/jpa-insert) -- [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) -- [Spring Data JPA Query by Example](https://www.baeldung.com/spring-data-query-by-example) -- [DB Integration Tests with Spring Boot and Testcontainers](https://www.baeldung.com/spring-boot-testcontainers-integration-test) -- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) - -### Eclipse Config -After importing the project into Eclipse, you may see the following error: -"No persistence xml file found in project" - -This can be ignored: -- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project" -Or: -- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator - From 683fc563a6e2f999e49ea4410b1994d384c630c3 Mon Sep 17 00:00:00 2001 From: Loredana Date: Sat, 23 Mar 2019 12:30:06 +0200 Subject: [PATCH 439/496] formatting --- core-java-12/pom.xml | 80 ++++++++--------- .../collectors/CollectorsUnitTest.java | 90 +++++++++---------- 2 files changed, 82 insertions(+), 88 deletions(-) diff --git a/core-java-12/pom.xml b/core-java-12/pom.xml index 729b29381b..defef5e9d3 100644 --- a/core-java-12/pom.xml +++ b/core-java-12/pom.xml @@ -1,48 +1,48 @@ - 4.0.0 - com.baeldung - core-java-12 - 0.1.0-SNAPSHOT - core-java-12 - jar - http://maven.apache.org + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung + core-java-12 + 0.1.0-SNAPSHOT + core-java-12 + jar + http://maven.apache.org - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + - - - org.assertj - assertj-core - ${assertj.version} - test - - + + + org.assertj + assertj-core + ${assertj.version} + test + + - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${maven.compiler.source.version} - ${maven.compiler.target.version} - - - - + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source.version} + ${maven.compiler.target.version} + + + + - - 12 - 12 - 3.6.1 - + + 12 + 12 + 3.6.1 + \ No newline at end of file diff --git a/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java b/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java index 68915b504d..7c4cb9e8f0 100644 --- a/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java +++ b/core-java-12/src/test/java/com/baeldung/collectors/CollectorsUnitTest.java @@ -16,62 +16,56 @@ import static org.assertj.core.api.Assertions.assertThat; */ public class CollectorsUnitTest { - @Test - public void whenTeeing_ItShouldCombineTheResultsAsExpected() { - List numbers = Arrays.asList(42, 4, 2, 24); - Range range = numbers.stream() - .collect(teeing( - minBy(Integer::compareTo), - maxBy(Integer::compareTo), - (min, max) -> new Range(min.orElse(null), max.orElse(null)) - )); + @Test + public void whenTeeing_ItShouldCombineTheResultsAsExpected() { + List numbers = Arrays.asList(42, 4, 2, 24); + Range range = numbers.stream() + .collect(teeing(minBy(Integer::compareTo), maxBy(Integer::compareTo), (min, max) -> new Range(min.orElse(null), max.orElse(null)))); - assertThat(range).isEqualTo(new Range(2, 42)); - } + assertThat(range).isEqualTo(new Range(2, 42)); + } - /** - * Represents a closed range of numbers between {@link #min} and - * {@link #max}, both inclusive. - */ - private static class Range { + /** + * Represents a closed range of numbers between {@link #min} and + * {@link #max}, both inclusive. + */ + private static class Range { - private final Integer min; + private final Integer min; - private final Integer max; + private final Integer max; - Range(Integer min, Integer max) { - this.min = min; - this.max = max; - } + Range(Integer min, Integer max) { + this.min = min; + this.max = max; + } - Integer getMin() { - return min; - } + Integer getMin() { + return min; + } - Integer getMax() { - return max; - } + Integer getMax() { + return max; + } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Range range = (Range) o; - return Objects.equals(getMin(), range.getMin()) && - Objects.equals(getMax(), range.getMax()); - } + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Range range = (Range) o; + return Objects.equals(getMin(), range.getMin()) && Objects.equals(getMax(), range.getMax()); + } - @Override - public int hashCode() { - return Objects.hash(getMin(), getMax()); - } + @Override + public int hashCode() { + return Objects.hash(getMin(), getMax()); + } - @Override - public String toString() { - return "Range{" + - "min=" + min + - ", max=" + max + - '}'; - } - } + @Override + public String toString() { + return "Range{" + "min=" + min + ", max=" + max + '}'; + } + } } From 1699e4c3bd50ab03f5e61830bfe7ce266d49f289 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Sat, 23 Mar 2019 15:24:57 +0400 Subject: [PATCH 440/496] Trove put values --- .../src/main/java/com/baeldung/map/PrimitiveMaps.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java b/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java index c13aa19424..10245ce6e0 100644 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java +++ b/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java @@ -59,8 +59,8 @@ public class PrimitiveMaps { TDoubleIntMap doubleIntMap = new TDoubleIntHashMap(doubles, ints); - doubleIntMap.adjustValue(1.2, 1); - doubleIntMap.adjustValue(4.5, 4); - doubleIntMap.adjustValue(0.3, 0); + doubleIntMap.put(1.2, 1); + doubleIntMap.put(4.5, 4); + doubleIntMap.put(0.3, 0); } } From 4372c6fa1cc44ab74053d532d599903a6786ae31 Mon Sep 17 00:00:00 2001 From: Sam Millington Date: Sat, 23 Mar 2019 11:51:30 +0000 Subject: [PATCH 441/496] [BAEL-2653] Added kotlin immutable collections code (#6563) * Added kotlin immutable collections code * corrected wrong junit version --- kotlin-libraries/pom.xml | 29 ++++++++ .../immutable/KotlinxImmutablesUnitTest.kt | 27 +++++++ .../kotlin/immutable/ReadOnlyUnitTest.kt | 73 +++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/immutable/KotlinxImmutablesUnitTest.kt create mode 100644 kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/immutable/ReadOnlyUnitTest.kt diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml index 507e5820d4..e3f69b4ea9 100644 --- a/kotlin-libraries/pom.xml +++ b/kotlin-libraries/pom.xml @@ -19,6 +19,14 @@ exposed https://dl.bintray.com/kotlin/exposed + + + false + + kotlinx + bintray + https://dl.bintray.com/kotlin/kotlinx + @@ -112,9 +120,30 @@ 3.3.0 pom + + + + junit + junit + ${junit.version} + test + + + + com.google.guava + guava + 27.1-jre + + + + org.jetbrains.kotlinx + kotlinx-collections-immutable + 0.1 + + 4.12 1.5.0 4.1.0 3.0.4 diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/immutable/KotlinxImmutablesUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/immutable/KotlinxImmutablesUnitTest.kt new file mode 100644 index 0000000000..971f2de4c2 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/immutable/KotlinxImmutablesUnitTest.kt @@ -0,0 +1,27 @@ +package com.baeldung.kotlin.immutable + +import junit.framework.Assert.assertEquals +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.immutableListOf +import org.junit.Rule +import org.junit.Test +import org.junit.rules.ExpectedException + +class KotlinxImmutablesUnitTest{ + + + @Rule + @JvmField + var ee : ExpectedException = ExpectedException.none() + + @Test + fun givenKICLList_whenAddTried_checkExceptionThrown(){ + + val list: ImmutableList = immutableListOf("I", "am", "immutable") + + list.add("My new item") + + assertEquals(listOf("I", "am", "immutable"), list) + + } +} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/immutable/ReadOnlyUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/immutable/ReadOnlyUnitTest.kt new file mode 100644 index 0000000000..62c4a4eb88 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/immutable/ReadOnlyUnitTest.kt @@ -0,0 +1,73 @@ +package com.baeldung.kotlin.immutable + +import com.google.common.collect.ImmutableList +import com.google.common.collect.ImmutableSet +import junit.framework.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.junit.rules.ExpectedException + +class ReadOnlyUnitTest{ + + @Test + fun givenReadOnlyList_whenCastToMutableList_checkNewElementsAdded(){ + + val list: List = listOf("This", "Is", "Totally", "Immutable") + + (list as MutableList)[2] = "Not" + + assertEquals(listOf("This", "Is", "Not", "Immutable"), list) + + } + + @Rule + @JvmField + var ee : ExpectedException = ExpectedException.none() + + @Test + fun givenImmutableList_whenAddTried_checkExceptionThrown(){ + + val list: List = ImmutableList.of("I", "am", "actually", "immutable") + + ee.expect(UnsupportedOperationException::class.java) + + (list as MutableList).add("Oops") + + } + + @Test + fun givenMutableList_whenCopiedAndAddTried_checkExceptionThrown(){ + + val mutableList : List = listOf("I", "Am", "Definitely", "Immutable") + + (mutableList as MutableList)[2] = "100% Not" + + assertEquals(listOf("I", "Am", "100% Not", "Immutable"), mutableList) + + val list: List = ImmutableList.copyOf(mutableList) + + ee.expect(UnsupportedOperationException::class.java) + + (list as MutableList)[2] = "Really?" + + } + + @Test + fun givenImmutableSetBuilder_whenAddTried_checkExceptionThrown(){ + + val mutableList : List = listOf("Hello", "Baeldung") + val set: ImmutableSet = ImmutableSet.builder() + .add("I","am","immutable") + .addAll(mutableList) + .build() + + assertEquals(setOf("Hello", "Baeldung", "I", "am", "immutable"), set) + + ee.expect(UnsupportedOperationException::class.java) + + (set as MutableSet).add("Oops") + + } + + +} \ No newline at end of file From 96b8a69f726dadae84c57700048d1dc57fa4138d Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Sat, 23 Mar 2019 13:36:10 +0100 Subject: [PATCH 442/496] Update spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml Co-Authored-By: cscib --- spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml b/spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml index 522013849b..908a545242 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 client-service - client-service + client-service 1.0-SNAPSHOT From 6f26499f3e1a9b27ee4e62c66fc252f18cb44f11 Mon Sep 17 00:00:00 2001 From: KevinGilmore Date: Sat, 23 Mar 2019 13:36:41 +0100 Subject: [PATCH 443/496] Update spring-cloud/spring-cloud-kubernetes-2/pom.xml Co-Authored-By: cscib --- spring-cloud/spring-cloud-kubernetes-2/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud/spring-cloud-kubernetes-2/pom.xml b/spring-cloud/spring-cloud-kubernetes-2/pom.xml index 1ce18a7498..d501e8102f 100644 --- a/spring-cloud/spring-cloud-kubernetes-2/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes-2/pom.xml @@ -5,7 +5,7 @@ com.baeldung.spring.cloud spring-cloud-kubernetes-2 1.0-SNAPSHOT - spring-cloud-kubernetes-2 + spring-cloud-kubernetes-2 pom From c03044e3efb56879dbd4266ef30a122a71ffa9f0 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Sat, 23 Mar 2019 07:45:04 -0500 Subject: [PATCH 444/496] BAEL-2724_Closures_in_groovy (#6439) * BAEL-2724_Closures_in_groovy * BAEL-2724_Closures_in_groovy * BAEL-2724_Closures_in_groovy * BAEL-2724_Closures_in_groovy * BAEL-2724_Closures_in_groovy * BAEL-2724_Closures_in_groovy * BAEL-2724_Closures_in_groovy * BAEL-2724_Closures_in_groovy * BAEL-2724_Closures_in_groovy --- .../com/baeldung/closures/Closures.groovy | 87 +++++++++++++++++++ .../com/baeldung/closures/Employee.groovy | 6 ++ .../baeldung/closures/ClosuresUnitTest.groovy | 80 +++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 core-groovy/src/main/groovy/com/baeldung/closures/Closures.groovy create mode 100644 core-groovy/src/main/groovy/com/baeldung/closures/Employee.groovy create mode 100644 core-groovy/src/test/groovy/com/baeldung/closures/ClosuresUnitTest.groovy diff --git a/core-groovy/src/main/groovy/com/baeldung/closures/Closures.groovy b/core-groovy/src/main/groovy/com/baeldung/closures/Closures.groovy new file mode 100644 index 0000000000..607329ce88 --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/closures/Closures.groovy @@ -0,0 +1,87 @@ +package com.baeldung.closures + +class Closures { + + def printWelcome = { + println "Welcome to Closures!" + } + + def print = { name -> + println name + } + + def formatToLowerCase(name) { + return name.toLowerCase() + } + def formatToLowerCaseClosure = { name -> + return name.toLowerCase() + } + + def count=0 + + def increaseCount = { + count++ + } + + def greet = { + return "Hello! ${it}" + } + + def multiply = { x, y -> + return x*y + } + + def calculate = {int x, int y, String operation -> + + //log closure + def log = { + println "Performing $it" + } + + def result = 0 + switch(operation) { + case "ADD": + log("Addition") + result = x+y + break + case "SUB": + log("Subtraction") + result = x-y + break + case "MUL": + log("Multiplication") + result = x*y + break + case "DIV": + log("Division") + result = x/y + break + } + return result + } + + def addAll = { int... args -> + return args.sum() + } + + def volume(Closure areaCalculator, int... dimensions) { + if(dimensions.size() == 3) { + + //consider dimension[0] = length, dimension[1] = breadth, dimension[2] = height + //for cube and cuboid + return areaCalculator(dimensions[0], dimensions[1]) * dimensions[2] + } else if(dimensions.size() == 2) { + + //consider dimension[0] = radius, dimension[1] = height + //for cylinder and cone + return areaCalculator(dimensions[0]) * dimensions[1] + } else if(dimensions.size() == 1) { + + //consider dimension[0] = radius + //for sphere + return areaCalculator(dimensions[0]) * dimensions[0] + } + + } + +} \ No newline at end of file diff --git a/core-groovy/src/main/groovy/com/baeldung/closures/Employee.groovy b/core-groovy/src/main/groovy/com/baeldung/closures/Employee.groovy new file mode 100644 index 0000000000..78eb5aadeb --- /dev/null +++ b/core-groovy/src/main/groovy/com/baeldung/closures/Employee.groovy @@ -0,0 +1,6 @@ +package com.baeldung.closures + +class Employee { + + String fullName +} \ No newline at end of file diff --git a/core-groovy/src/test/groovy/com/baeldung/closures/ClosuresUnitTest.groovy b/core-groovy/src/test/groovy/com/baeldung/closures/ClosuresUnitTest.groovy new file mode 100644 index 0000000000..32c67e99bc --- /dev/null +++ b/core-groovy/src/test/groovy/com/baeldung/closures/ClosuresUnitTest.groovy @@ -0,0 +1,80 @@ +package com.baeldung.closures + +import spock.lang.Specification + +class ClosuresUnitTest extends GroovyTestCase { + + Closures closures = new Closures() + + void testDeclaration() { + + closures.print("Hello! Closure") + closures.formatToLowerCaseClosure("Hello! Closure") + + closures.print.call("Hello! Closure") + closures.formatToLowerCaseClosure.call("Hello! Closure") + + } + + void testClosureVsMethods() { + assert closures.formatToLowerCase("TONY STARK") == closures.formatToLowerCaseClosure("Tony STark") + } + + void testParameters() { + //implicit parameter + assert closures.greet("Alex") == "Hello! Alex" + + //multiple parameters + assert closures.multiply(2, 4) == 8 + + assert closures.calculate(12, 4, "ADD") == 16 + assert closures.calculate(12, 4, "SUB") == 8 + assert closures.calculate(43, 8, "DIV") == 5.375 + + //varags + assert closures.addAll(12, 10, 14) == 36 + + } + + void testClosureAsAnArgument() { + assert closures.volume({ l, b -> return l*b }, 12, 6, 10) == 720 + + assert closures.volume({ radius -> return Math.PI*radius*radius/3 }, 5, 10) == Math.PI * 250/3 + } + + void testGStringsLazyEvaluation() { + def name = "Samwell" + def welcomeMsg = "Welcome! $name" + + assert welcomeMsg == "Welcome! Samwell" + + // changing the name does not affect original interpolated value + name = "Tarly" + assert welcomeMsg != "Welcome! Tarly" + + def fullName = "Tarly Samson" + def greetStr = "Hello! ${-> fullName}" + + assert greetStr == "Hello! Tarly Samson" + + // this time changing the variable affects the interpolated String's value + fullName = "Jon Smith" + assert greetStr == "Hello! Jon Smith" + } + + void testClosureInLists() { + def list = [10, 11, 12, 13, 14, true, false, "BUNTHER"] + list.each { + println it + } + + assert [13, 14] == list.findAll{ it instanceof Integer && it >= 13} + } + + void testClosureInMaps() { + def map = [1:10, 2:30, 4:5] + + assert [10, 60, 20] == map.collect{it.key * it.value} + } + +} \ No newline at end of file From e5477a37282ce2482ae2acc7f1818a5db0e09164 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sat, 23 Mar 2019 23:56:46 +0530 Subject: [PATCH 445/496] [BAEL-10982] - Fixed live tests in spring rest template module, added missing methods in controller --- .../configuration/FooController.java | 124 ++++++++ .../RestTemplateResponseErrorHandler.java | 6 +- .../client/RestTemplateBasicLiveTest.java | 272 ++++++++++++++++++ .../client/TestRestTemplateBasicLiveTest.java | 123 ++++++++ 4 files changed, 523 insertions(+), 2 deletions(-) create mode 100644 spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/FooController.java create mode 100644 spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java create mode 100644 spring-resttemplate/src/test/java/org/baeldung/client/TestRestTemplateBasicLiveTest.java diff --git a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/FooController.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/FooController.java new file mode 100644 index 0000000000..a9d400b199 --- /dev/null +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/configuration/FooController.java @@ -0,0 +1,124 @@ +package org.baeldung.resttemplate.configuration; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; + +import java.net.URI; +import java.util.Collection; +import java.util.Map; + +import org.baeldung.resttemplate.web.dto.Foo; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +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.ResponseStatus; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; + +@Controller +public class FooController { + + private Map fooRepository = Maps.newHashMap(ImmutableMap.of(1L, new Foo(1L, randomAlphabetic(4)))); + + public FooController() { + super(); + } + + @RequestMapping(method = RequestMethod.GET, value = "/foos") + @ResponseBody + public Collection findListOfFoo() { + return fooRepository.values(); + } + + // API - read + + @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") + @ResponseBody + public Foo findById(@PathVariable final long id) throws HttpClientErrorException { + Foo foo = fooRepository.get(id); + + if (foo == null) { + throw new HttpClientErrorException(HttpStatus.NOT_FOUND); + } else { + return foo; + } + } + + // API - write + + @RequestMapping(method = RequestMethod.PUT, value = "/foos/{id}") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public Foo updateFoo(@PathVariable("id") final long id, @RequestBody final Foo foo) { + fooRepository.put(id, foo); + return foo; + } + + @RequestMapping(method = RequestMethod.PATCH, value = "/foos/{id}") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public Foo patchFoo(@PathVariable("id") final long id, @RequestBody final Foo foo) { + fooRepository.put(id, foo); + return foo; + } + + @RequestMapping(method = RequestMethod.POST, value = "/foos") + @ResponseStatus(HttpStatus.CREATED) + @ResponseBody + public ResponseEntity postFoo(@RequestBody final Foo foo) { + + fooRepository.put(foo.getId(), foo); + final URI location = ServletUriComponentsBuilder + .fromCurrentServletMapping() + .path("/foos/{id}") + .build() + .expand(foo.getId()) + .toUri(); + + final HttpHeaders headers = new HttpHeaders(); + headers.setLocation(location); + + final ResponseEntity entity = new ResponseEntity(foo, headers, HttpStatus.CREATED); + return entity; + } + + @RequestMapping(method = RequestMethod.HEAD, value = "/foos") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public Foo headFoo() { + return new Foo(1, randomAlphabetic(4)); + } + + @RequestMapping(method = RequestMethod.POST, value = "/foos/new") + @ResponseStatus(HttpStatus.CREATED) + @ResponseBody + public Foo createFoo(@RequestBody final Foo foo) { + fooRepository.put(foo.getId(), foo); + return foo; + } + + @RequestMapping(method = RequestMethod.DELETE, value = "/foos/{id}") + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public long deleteFoo(@PathVariable final long id) { + fooRepository.remove(id); + return id; + } + + @RequestMapping(method = RequestMethod.POST, value = "/foos/form") + @ResponseStatus(HttpStatus.CREATED) + @ResponseBody + public String submitFoo(@RequestParam("id") String id) { + return id; + } + +} diff --git a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java index d65e837067..214de38746 100644 --- a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java +++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java @@ -1,13 +1,14 @@ package org.baeldung.resttemplate.web.handler; +import java.io.IOException; + import org.baeldung.resttemplate.web.exception.NotFoundException; import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.ResponseErrorHandler; -import java.io.IOException; - @Component public class RestTemplateResponseErrorHandler implements ResponseErrorHandler { @@ -31,6 +32,7 @@ public class RestTemplateResponseErrorHandler .getStatusCode() .series() == HttpStatus.Series.SERVER_ERROR) { //Handle SERVER_ERROR + throw new HttpClientErrorException(httpResponse.getStatusCode()); } else if (httpResponse .getStatusCode() .series() == HttpStatus.Series.CLIENT_ERROR) { diff --git a/spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java b/spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java new file mode 100644 index 0000000000..a54c124d5f --- /dev/null +++ b/spring-resttemplate/src/test/java/org/baeldung/client/RestTemplateBasicLiveTest.java @@ -0,0 +1,272 @@ +package org.baeldung.client; + +import static org.apache.commons.codec.binary.Base64.encodeBase64; +import static org.baeldung.client.Consts.APPLICATION_PORT; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; +import java.util.Set; + +import org.baeldung.resttemplate.web.dto.Foo; +import org.baeldung.resttemplate.web.handler.RestTemplateResponseErrorHandler; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RequestCallback; +import org.springframework.web.client.RestTemplate; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import com.google.common.base.Charsets; + +public class RestTemplateBasicLiveTest { + + private RestTemplate restTemplate; + private static final String fooResourceUrl = "http://localhost:" + APPLICATION_PORT + "/spring-rest/foos"; + + @Before + public void beforeTest() { + restTemplate = new RestTemplate(); + restTemplate.setErrorHandler(new RestTemplateResponseErrorHandler()); + // restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter())); + } + + // GET + + @Test + public void givenResourceUrl_whenSendGetForRequestEntity_thenStatusOk() throws IOException { + final ResponseEntity response = restTemplate.getForEntity(fooResourceUrl + "/1", Foo.class); + + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } + + @Test + public void givenResourceUrl_whenSendGetForRequestEntity_thenBodyCorrect() throws IOException { + final RestTemplate template = new RestTemplate(); + final ResponseEntity response = template.getForEntity(fooResourceUrl + "/1", String.class); + + final ObjectMapper mapper = new XmlMapper(); + final JsonNode root = mapper.readTree(response.getBody()); + final JsonNode name = root.path("name"); + assertThat(name.asText(), notNullValue()); + } + + @Test + public void givenResourceUrl_whenRetrievingResource_thenCorrect() throws IOException { + final Foo foo = restTemplate.getForObject(fooResourceUrl + "/1", Foo.class); + + assertThat(foo.getName(), notNullValue()); + assertThat(foo.getId(), is(1L)); + } + + // HEAD, OPTIONS + + @Test + public void givenFooService_whenCallHeadForHeaders_thenReceiveAllHeadersForThatResource() { + final HttpHeaders httpHeaders = restTemplate.headForHeaders(fooResourceUrl); + assertTrue(httpHeaders.getContentType() + .includes(MediaType.APPLICATION_JSON)); + } + + // POST + + @Test + public void givenFooService_whenPostForObject_thenCreatedObjectIsReturned() { + final HttpEntity request = new HttpEntity<>(new Foo("bar")); + final Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.class); + assertThat(foo, notNullValue()); + assertThat(foo.getName(), is("bar")); + } + + @Test + public void givenFooService_whenPostForLocation_thenCreatedLocationIsReturned() { + final HttpEntity request = new HttpEntity<>(new Foo("bar")); + final URI location = restTemplate.postForLocation(fooResourceUrl, request, Foo.class); + assertThat(location, notNullValue()); + } + + @Test + public void givenFooService_whenPostResource_thenResourceIsCreated() { + final Foo foo = new Foo("bar"); + final ResponseEntity response = restTemplate.postForEntity(fooResourceUrl, foo, Foo.class); + + assertThat(response.getStatusCode(), is(HttpStatus.CREATED)); + final Foo fooResponse = response.getBody(); + assertThat(fooResponse, notNullValue()); + assertThat(fooResponse.getName(), is("bar")); + } + + @Test + public void givenFooService_whenCallOptionsForAllow_thenReceiveValueOfAllowHeader() { + final Set optionsForAllow = restTemplate.optionsForAllow(fooResourceUrl); + final HttpMethod[] supportedMethods = { HttpMethod.GET, HttpMethod.POST, HttpMethod.HEAD }; + + assertTrue(optionsForAllow.containsAll(Arrays.asList(supportedMethods))); + } + + // PUT + + @Test + public void givenFooService_whenPutExistingEntity_thenItIsUpdated() { + final HttpHeaders headers = prepareBasicAuthHeaders(); + final HttpEntity request = new HttpEntity<>(new Foo("bar"), headers); + + // Create Resource + final ResponseEntity createResponse = restTemplate.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class); + + // Update Resource + final Foo updatedInstance = new Foo("newName"); + updatedInstance.setId(createResponse.getBody() + .getId()); + final String resourceUrl = fooResourceUrl + '/' + createResponse.getBody() + .getId(); + final HttpEntity requestUpdate = new HttpEntity<>(updatedInstance, headers); + restTemplate.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Void.class); + + // Check that Resource was updated + final ResponseEntity updateResponse = restTemplate.exchange(resourceUrl, HttpMethod.GET, new HttpEntity<>(headers), Foo.class); + final Foo foo = updateResponse.getBody(); + assertThat(foo.getName(), is(updatedInstance.getName())); + } + + @Test + public void givenFooService_whenPutExistingEntityWithCallback_thenItIsUpdated() { + final HttpHeaders headers = prepareBasicAuthHeaders(); + final HttpEntity request = new HttpEntity<>(new Foo("bar"), headers); + + // Create entity + ResponseEntity response = restTemplate.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class); + assertThat(response.getStatusCode(), is(HttpStatus.CREATED)); + + // Update entity + final Foo updatedInstance = new Foo("newName"); + updatedInstance.setId(response.getBody() + .getId()); + final String resourceUrl = fooResourceUrl + '/' + response.getBody() + .getId(); + restTemplate.execute(resourceUrl, HttpMethod.PUT, requestCallback(updatedInstance), clientHttpResponse -> null); + + // Check that entity was updated + response = restTemplate.exchange(resourceUrl, HttpMethod.GET, new HttpEntity<>(headers), Foo.class); + final Foo foo = response.getBody(); + assertThat(foo.getName(), is(updatedInstance.getName())); + } + + // PATCH + + @Test + public void givenFooService_whenPatchExistingEntity_thenItIsUpdated() { + final HttpHeaders headers = prepareBasicAuthHeaders(); + final HttpEntity request = new HttpEntity<>(new Foo("bar"), headers); + + // Create Resource + final ResponseEntity createResponse = restTemplate.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.class); + + // Update Resource + final Foo updatedResource = new Foo("newName"); + updatedResource.setId(createResponse.getBody() + .getId()); + final String resourceUrl = fooResourceUrl + '/' + createResponse.getBody() + .getId(); + final HttpEntity requestUpdate = new HttpEntity<>(updatedResource, headers); + final ClientHttpRequestFactory requestFactory = getSimpleClientHttpRequestFactory(); + final RestTemplate template = new RestTemplate(requestFactory); + template.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter())); + template.patchForObject(resourceUrl, requestUpdate, Void.class); + + // Check that Resource was updated + final ResponseEntity updateResponse = restTemplate.exchange(resourceUrl, HttpMethod.GET, new HttpEntity<>(headers), Foo.class); + final Foo foo = updateResponse.getBody(); + assertThat(foo.getName(), is(updatedResource.getName())); + } + + // DELETE + + @Test + public void givenFooService_whenCallDelete_thenEntityIsRemoved() { + final Foo foo = new Foo("remove me"); + final ResponseEntity response = restTemplate.postForEntity(fooResourceUrl, foo, Foo.class); + assertThat(response.getStatusCode(), is(HttpStatus.CREATED)); + + final String entityUrl = fooResourceUrl + "/" + response.getBody() + .getId(); + restTemplate.delete(entityUrl); + try { + restTemplate.getForEntity(entityUrl, Foo.class); + fail(); + } catch (final HttpClientErrorException ex) { + assertThat(ex.getStatusCode(), is(HttpStatus.INTERNAL_SERVER_ERROR)); + } + } + + @Test + public void givenFooService_whenFormSubmit_thenResourceIsCreated() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + MultiValueMap map= new LinkedMultiValueMap<>(); + map.add("id", "10"); + + HttpEntity> request = new HttpEntity<>(map, headers); + + ResponseEntity response = restTemplate.postForEntity( fooResourceUrl+"/form", request , String.class); + + assertThat(response.getStatusCode(), is(HttpStatus.CREATED)); + final String fooResponse = response.getBody(); + assertThat(fooResponse, notNullValue()); + assertThat(fooResponse, is("10")); + } + + private HttpHeaders prepareBasicAuthHeaders() { + final HttpHeaders headers = new HttpHeaders(); + final String encodedLogPass = getBase64EncodedLogPass(); + headers.add(HttpHeaders.AUTHORIZATION, "Basic " + encodedLogPass); + return headers; + } + + private String getBase64EncodedLogPass() { + final String logPass = "user1:user1Pass"; + final byte[] authHeaderBytes = encodeBase64(logPass.getBytes(Charsets.US_ASCII)); + return new String(authHeaderBytes, Charsets.US_ASCII); + } + + private RequestCallback requestCallback(final Foo updatedInstance) { + return clientHttpRequest -> { + final ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(clientHttpRequest.getBody(), updatedInstance); + clientHttpRequest.getHeaders() + .add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + clientHttpRequest.getHeaders() + .add(HttpHeaders.AUTHORIZATION, "Basic " + getBase64EncodedLogPass()); + }; + } + + // Simply setting restTemplate timeout using ClientHttpRequestFactory + + ClientHttpRequestFactory getSimpleClientHttpRequestFactory() { + final int timeout = 5; + final HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); + clientHttpRequestFactory.setConnectTimeout(timeout * 1000); + return clientHttpRequestFactory; + } + +} diff --git a/spring-resttemplate/src/test/java/org/baeldung/client/TestRestTemplateBasicLiveTest.java b/spring-resttemplate/src/test/java/org/baeldung/client/TestRestTemplateBasicLiveTest.java new file mode 100644 index 0000000000..967c4a6188 --- /dev/null +++ b/spring-resttemplate/src/test/java/org/baeldung/client/TestRestTemplateBasicLiveTest.java @@ -0,0 +1,123 @@ +package org.baeldung.client; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertTrue; + +import org.baeldung.resttemplate.web.dto.Foo; +import org.junit.Before; +import org.junit.Test; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import okhttp3.Request; +import okhttp3.RequestBody; + +public class TestRestTemplateBasicLiveTest { + + private RestTemplate restTemplate; + + private static final String FOO_RESOURCE_URL = "http://localhost:" + 8082 + "/spring-rest/foos"; + private static final String URL_SECURED_BY_AUTHENTICATION = "http://httpbin.org/basic-auth/user/passwd"; + private static final String BASE_URL = "http://localhost:" + 8082 + "/spring-rest"; + + @Before + public void beforeTest() { + restTemplate = new RestTemplate(); + } + + // GET + @Test + public void givenTestRestTemplate_whenSendGetForEntity_thenStatusOk() { + TestRestTemplate testRestTemplate = new TestRestTemplate(); + ResponseEntity response = testRestTemplate.getForEntity(FOO_RESOURCE_URL + "/1", Foo.class); + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } + + @Test + public void givenRestTemplateWrapper_whenSendGetForEntity_thenStatusOk() { + RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); + restTemplateBuilder.configure(restTemplate); + TestRestTemplate testRestTemplate = new TestRestTemplate(restTemplateBuilder); + ResponseEntity response = testRestTemplate.getForEntity(FOO_RESOURCE_URL + "/1", Foo.class); + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } + + @Test + public void givenRestTemplateBuilderWrapper_whenSendGetForEntity_thenStatusOk() { + RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); + restTemplateBuilder.build(); + TestRestTemplate testRestTemplate = new TestRestTemplate(restTemplateBuilder); + ResponseEntity response = testRestTemplate.getForEntity(FOO_RESOURCE_URL + "/1", Foo.class); + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } + + @Test + public void givenRestTemplateWrapperWithCredentials_whenSendGetForEntity_thenStatusOk() { + RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(); + restTemplateBuilder.configure(restTemplate); + TestRestTemplate testRestTemplate = new TestRestTemplate(restTemplateBuilder, "user", "passwd"); + ResponseEntity response = testRestTemplate.getForEntity(URL_SECURED_BY_AUTHENTICATION, + String.class); + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } + + @Test + public void givenTestRestTemplateWithCredentials_whenSendGetForEntity_thenStatusOk() { + TestRestTemplate testRestTemplate = new TestRestTemplate("user", "passwd"); + ResponseEntity response = testRestTemplate.getForEntity(URL_SECURED_BY_AUTHENTICATION, + String.class); + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } + + @Test + public void givenTestRestTemplateWithBasicAuth_whenSendGetForEntity_thenStatusOk() { + TestRestTemplate testRestTemplate = new TestRestTemplate(); + ResponseEntity response = testRestTemplate.withBasicAuth("user", "passwd"). + getForEntity(URL_SECURED_BY_AUTHENTICATION, String.class); + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } + + @Test + public void givenTestRestTemplateWithCredentialsAndEnabledCookies_whenSendGetForEntity_thenStatusOk() { + TestRestTemplate testRestTemplate = new TestRestTemplate("user", "passwd", TestRestTemplate. + HttpClientOption.ENABLE_COOKIES); + ResponseEntity response = testRestTemplate.getForEntity(URL_SECURED_BY_AUTHENTICATION, + String.class); + assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + } + + // HEAD + @Test + public void givenFooService_whenCallHeadForHeaders_thenReceiveAllHeaders() { + TestRestTemplate testRestTemplate = new TestRestTemplate(); + final HttpHeaders httpHeaders = testRestTemplate.headForHeaders(FOO_RESOURCE_URL); + assertTrue(httpHeaders.getContentType().includes(MediaType.APPLICATION_JSON)); + } + + // POST + @Test + public void givenService_whenPostForObject_thenCreatedObjectIsReturned() { + TestRestTemplate testRestTemplate = new TestRestTemplate("user", "passwd"); + final RequestBody body = RequestBody.create(okhttp3.MediaType.parse("text/html; charset=utf-8"), + "{\"id\":1,\"name\":\"Jim\"}"); + final Request request = new Request.Builder().url(BASE_URL + "/users/detail").post(body).build(); + testRestTemplate.postForObject(URL_SECURED_BY_AUTHENTICATION, request, String.class); + } + + // PUT + @Test + public void givenService_whenPutForObject_thenCreatedObjectIsReturned() { + TestRestTemplate testRestTemplate = new TestRestTemplate("user", "passwd"); + final RequestBody body = RequestBody.create(okhttp3.MediaType.parse("text/html; charset=utf-8"), + "{\"id\":1,\"name\":\"Jim\"}"); + final Request request = new Request.Builder().url(BASE_URL + "/users/detail").post(body).build(); + testRestTemplate.put(URL_SECURED_BY_AUTHENTICATION, request, String.class); + } + +} From 7bb1a28235e1c81538e1526823233b31f7eb1615 Mon Sep 17 00:00:00 2001 From: "anilkivilcim.eray" Date: Sat, 23 Mar 2019 22:07:24 +0300 Subject: [PATCH 446/496] BAEL-2762 formating done for 2 space indenting --- .../config/BasicAuthConfiguration.java | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java index 6d769017bd..592ef5354d 100644 --- a/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java +++ b/spring-boot-security/src/main/java/com/baeldung/springbootsecurity/basic_auth/config/BasicAuthConfiguration.java @@ -14,27 +14,25 @@ public class BasicAuthConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { - PasswordEncoder encoder = - PasswordEncoderFactories.createDelegatingPasswordEncoder(); - - auth - .inMemoryAuthentication() - .withUser("user") - .password(encoder.encode("password")) - .roles("USER") - .and() - .withUser("admin") - .password(encoder.encode("admin")) - .roles("USER", "ADMIN"); + PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); + auth + .inMemoryAuthentication() + .withUser("user") + .password(encoder.encode("password")) + .roles("USER") + .and() + .withUser("admin") + .password(encoder.encode("admin")) + .roles("USER", "ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http - .authorizeRequests() - .anyRequest() - .authenticated() - .and() - .httpBasic(); + .authorizeRequests() + .anyRequest() + .authenticated() + .and() + .httpBasic(); } } From 8a2e671a11a6f704ae3dc95834bbd85a44b1b411 Mon Sep 17 00:00:00 2001 From: "sumit.sg34" Date: Sun, 24 Mar 2019 09:14:39 +0530 Subject: [PATCH 447/496] Fixed test case names --- .../repository/FruitRepositoryIntegrationTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java index 74188497ee..866cf1157b 100644 --- a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitRepositoryIntegrationTest.java @@ -25,7 +25,7 @@ class FruitRepositoryIntegrationTest { @Transactional @Test @Sql(scripts = { "/test-fruit-data.sql" }) - public void givenFruits_WhenDeletedByColor_DeletedFruitShouldReturn() { + public void givenFruits_WhenDeletedByColor_ThenDeletedFruitsShouldReturn() { List fruits = fruitRepository.deleteByColor("green"); @@ -36,7 +36,7 @@ class FruitRepositoryIntegrationTest { @Transactional @Test @Sql(scripts = { "/test-fruit-data.sql" }) - public void givenFruits_WhenDeletedByName_DeletedFruitCountShouldReturn() { + public void givenFruits_WhenDeletedByName_ThenDeletedFruitCountShouldReturn() { Long deletedFruitCount = fruitRepository.deleteByName("apple"); @@ -46,7 +46,7 @@ class FruitRepositoryIntegrationTest { @Transactional @Test @Sql(scripts = { "/test-fruit-data.sql" }) - public void givenFruits_WhenRemovedByColor_DeletedFruitShouldReturn() { + public void givenFruits_WhenRemovedByColor_ThenDeletedFruitsShouldReturn() { List fruits = fruitRepository.removeByColor("green"); @@ -57,7 +57,7 @@ class FruitRepositoryIntegrationTest { @Transactional @Test @Sql(scripts = { "/test-fruit-data.sql" }) - public void givenFruits_WhenRemovedByName_DeletedFruitCountShouldReturn() { + public void givenFruits_WhenRemovedByName_ThenDeletedFruitCountShouldReturn() { Long deletedFruitCount = fruitRepository.removeByName("apple"); @@ -67,7 +67,7 @@ class FruitRepositoryIntegrationTest { @Transactional @Test @Sql(scripts = { "/test-fruit-data.sql" }) - public void givenFruits_WhenDeletedByColorOrName_DeletedFruitShouldReturn() { + public void givenFruits_WhenDeletedByColorOrName_ThenDeletedFruitsShouldReturn() { List fruits = fruitRepository.deleteFruits("apple", "green"); From 8b491802f4774fdf337e0a7043d119dbddea14a1 Mon Sep 17 00:00:00 2001 From: mherbaghinyan Date: Sun, 24 Mar 2019 11:05:18 +0400 Subject: [PATCH 448/496] Trove adjustValue --- .../src/main/java/com/baeldung/map/PrimitiveMaps.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java b/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java index 10245ce6e0..d835950c68 100644 --- a/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java +++ b/java-collections-maps-2/src/main/java/com/baeldung/map/PrimitiveMaps.java @@ -59,8 +59,11 @@ public class PrimitiveMaps { TDoubleIntMap doubleIntMap = new TDoubleIntHashMap(doubles, ints); - doubleIntMap.put(1.2, 1); - doubleIntMap.put(4.5, 4); - doubleIntMap.put(0.3, 0); + doubleIntMap.put(1.2, 22); + doubleIntMap.put(4.5, 16); + + doubleIntMap.adjustValue(1.2, 1); + doubleIntMap.adjustValue(4.5, 4); + doubleIntMap.adjustValue(0.3, 7); } } From 3e926d56becc538ac0f44945add149432fdea3f9 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 24 Mar 2019 22:37:08 +0530 Subject: [PATCH 449/496] [BAEL-10897] - Fixed spring-boot-persistence tests --- .../spring-boot-persistence/pom.xml | 6 +++++ .../com/baeldung/{ => boot}/Application.java | 2 +- .../baeldung/{ => boot}/domain/Country.java | 2 +- .../com/baeldung/{ => boot}/domain/User.java | 2 +- .../{ => boot}/naming/HibernateConfig.java | 2 +- .../naming/MetadataExtractorIntegrator.java | 2 +- .../{ => boot}/naming/entity/Account.java | 2 +- .../{ => boot}/naming/entity/Preference.java | 2 +- .../{ => boot}/repository/UserRepository.java | 5 +++-- .../baeldung/SpringBootH2IntegrationTest.java | 1 + .../SpringBootJPAIntegrationTest.java | 1 + .../SpringBootProfileIntegrationTest.java | 5 +++-- .../LegacyJpaImplNamingIntegrationTest.java | 8 +++++-- .../{ => boot}/naming/NamingConfig.java | 2 +- ...pringBootDefaultNamingIntegrationTest.java | 8 ++++--- .../StrategyLegacyHbmImplIntegrationTest.java | 9 ++++++-- .../test}/UserRepositoryIntegrationTest.java | 8 ++++--- .../config/H2TestProfileJPAConfig.java | 2 +- .../tests/UserRepositoryIntegrationTest.java | 22 ++++++++++--------- ...otTomcatConnectionPoolIntegrationTest.java | 7 ++++-- 20 files changed, 63 insertions(+), 35 deletions(-) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{ => boot}/Application.java (93%) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{ => boot}/domain/Country.java (94%) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{ => boot}/domain/User.java (96%) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{ => boot}/naming/HibernateConfig.java (95%) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{ => boot}/naming/MetadataExtractorIntegrator.java (97%) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{ => boot}/naming/entity/Account.java (90%) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{ => boot}/naming/entity/Preference.java (84%) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{ => boot}/repository/UserRepository.java (97%) rename persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/{ => boot}/naming/LegacyJpaImplNamingIntegrationTest.java (90%) rename persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/{ => boot}/naming/NamingConfig.java (92%) rename persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/{ => boot}/naming/SpringBootDefaultNamingIntegrationTest.java (90%) rename persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/{ => boot}/naming/StrategyLegacyHbmImplIntegrationTest.java (88%) rename persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/{repository => boot/test}/UserRepositoryIntegrationTest.java (79%) rename persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/{ => application}/tests/UserRepositoryIntegrationTest.java (84%) diff --git a/persistence-modules/spring-boot-persistence/pom.xml b/persistence-modules/spring-boot-persistence/pom.xml index d9d3a9f9b7..72ac40222f 100644 --- a/persistence-modules/spring-boot-persistence/pom.xml +++ b/persistence-modules/spring-boot-persistence/pom.xml @@ -48,6 +48,11 @@ mysql mysql-connector-java + + javax.validation + validation-api + ${validation-api.version} + @@ -73,6 +78,7 @@ 9.0.10 1.4.197 2.23.0 + 2.0.1.Final diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/Application.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/Application.java similarity index 93% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/Application.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/Application.java index 43888c2d67..cb0d0c1532 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/Application.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/Application.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/domain/Country.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Country.java similarity index 94% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/domain/Country.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Country.java index e6a88c7121..59227f6412 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/domain/Country.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Country.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import static javax.persistence.GenerationType.IDENTITY; diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/domain/User.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/User.java similarity index 96% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/domain/User.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/User.java index 9d1fc4c8ad..bdbe75cd0c 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/domain/User.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/User.java @@ -1,4 +1,4 @@ -package com.baeldung.domain; +package com.baeldung.boot.domain; import javax.persistence.Entity; import javax.persistence.GeneratedValue; diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/HibernateConfig.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/HibernateConfig.java similarity index 95% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/HibernateConfig.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/HibernateConfig.java index 897e34d406..adde46e2b6 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/HibernateConfig.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/HibernateConfig.java @@ -1,4 +1,4 @@ -package com.baeldung.naming; +package com.baeldung.boot.naming; import org.hibernate.jpa.boot.spi.IntegratorProvider; import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer; diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/MetadataExtractorIntegrator.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/MetadataExtractorIntegrator.java similarity index 97% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/MetadataExtractorIntegrator.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/MetadataExtractorIntegrator.java index 24b5cdea64..8702624d3f 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/MetadataExtractorIntegrator.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/MetadataExtractorIntegrator.java @@ -1,4 +1,4 @@ -package com.baeldung.naming; +package com.baeldung.boot.naming; import org.hibernate.boot.Metadata; import org.hibernate.boot.model.relational.Database; diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Account.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Account.java similarity index 90% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Account.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Account.java index 6145818c5b..00e90a5ec9 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Account.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Account.java @@ -1,4 +1,4 @@ -package com.baeldung.naming.entity; +package com.baeldung.boot.naming.entity; import javax.persistence.Column; import javax.persistence.Entity; diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Preference.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Preference.java similarity index 84% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Preference.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Preference.java index 928884a2c5..7711156864 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/naming/entity/Preference.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/naming/entity/Preference.java @@ -1,4 +1,4 @@ -package com.baeldung.naming.entity; +package com.baeldung.boot.naming.entity; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/repository/UserRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/UserRepository.java similarity index 97% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/repository/UserRepository.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/UserRepository.java index bdc1e0af33..eae80b2e92 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/repository/UserRepository.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/UserRepository.java @@ -1,6 +1,5 @@ -package com.baeldung.repository; +package com.baeldung.boot.repository; -import com.baeldung.domain.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -11,6 +10,8 @@ import org.springframework.data.repository.query.Param; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Repository; +import com.baeldung.boot.domain.User; + import java.util.Collection; import java.util.List; import java.util.Optional; diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java index ecacf62285..01082cc6e2 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import com.baeldung.boot.Application; import com.baeldung.boot.config.H2JpaConfig; import com.baeldung.boot.domain.GenericEntity; import com.baeldung.boot.repository.GenericEntityRepository; diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootJPAIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootJPAIntegrationTest.java index 01fae2fb4d..f1ab442949 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootJPAIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootJPAIntegrationTest.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; +import com.baeldung.boot.Application; import com.baeldung.boot.domain.GenericEntity; import com.baeldung.boot.repository.GenericEntityRepository; diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootProfileIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootProfileIntegrationTest.java index 65a75d7bfe..0227458987 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootProfileIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootProfileIntegrationTest.java @@ -10,12 +10,13 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; +import com.baeldung.boot.Application; +import com.baeldung.boot.config.H2JpaConfig; import com.baeldung.boot.domain.GenericEntity; import com.baeldung.boot.repository.GenericEntityRepository; -import com.baeldung.config.H2TestProfileJPAConfig; @RunWith(SpringRunner.class) -@SpringBootTest(classes = { Application.class, H2TestProfileJPAConfig.class }) +@SpringBootTest(classes = { Application.class, H2JpaConfig.class }) @ActiveProfiles("test") public class SpringBootProfileIntegrationTest { @Autowired diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/LegacyJpaImplNamingIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/LegacyJpaImplNamingIntegrationTest.java similarity index 90% rename from persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/LegacyJpaImplNamingIntegrationTest.java rename to persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/LegacyJpaImplNamingIntegrationTest.java index e68be3bed8..2feee10980 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/LegacyJpaImplNamingIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/LegacyJpaImplNamingIntegrationTest.java @@ -1,6 +1,5 @@ -package com.baeldung.naming; +package com.baeldung.boot.naming; -import com.baeldung.naming.entity.Account; import org.assertj.core.api.SoftAssertions; import org.hibernate.boot.Metadata; import org.hibernate.mapping.PersistentClass; @@ -8,15 +7,20 @@ import org.hibernate.mapping.Table; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; +import com.baeldung.boot.naming.NamingConfig.Config; +import com.baeldung.boot.naming.entity.Account; + @RunWith(SpringRunner.class) @DataJpaTest @TestPropertySource(properties = { "spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl", "spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl" }) +@Import(Config.class) public class LegacyJpaImplNamingIntegrationTest extends NamingConfig { @Test diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/NamingConfig.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/NamingConfig.java similarity index 92% rename from persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/NamingConfig.java rename to persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/NamingConfig.java index c3ef37aeb4..9b6574b1d7 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/NamingConfig.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/NamingConfig.java @@ -1,4 +1,4 @@ -package com.baeldung.naming; +package com.baeldung.boot.naming; import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer; import org.springframework.boot.test.context.TestConfiguration; diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/SpringBootDefaultNamingIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/SpringBootDefaultNamingIntegrationTest.java similarity index 90% rename from persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/SpringBootDefaultNamingIntegrationTest.java rename to persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/SpringBootDefaultNamingIntegrationTest.java index 089430aabb..c5c320f70c 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/SpringBootDefaultNamingIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/SpringBootDefaultNamingIntegrationTest.java @@ -1,6 +1,5 @@ -package com.baeldung.naming; +package com.baeldung.boot.naming; -import com.baeldung.naming.entity.Account; import org.assertj.core.api.SoftAssertions; import org.hibernate.boot.Metadata; import org.hibernate.mapping.PersistentClass; @@ -8,10 +7,12 @@ import org.hibernate.mapping.Table; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; -import static org.assertj.core.api.Assertions.assertThat; +import com.baeldung.boot.naming.NamingConfig.Config; +import com.baeldung.boot.naming.entity.Account; @RunWith(SpringRunner.class) @DataJpaTest @@ -19,6 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat; "spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy", "spring.jpa.hibernate.naming.implicit-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy" }) +@Import(Config.class) public class SpringBootDefaultNamingIntegrationTest extends NamingConfig { @Test diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/StrategyLegacyHbmImplIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/StrategyLegacyHbmImplIntegrationTest.java similarity index 88% rename from persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/StrategyLegacyHbmImplIntegrationTest.java rename to persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/StrategyLegacyHbmImplIntegrationTest.java index 046755d9bc..ef978e5a98 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/naming/StrategyLegacyHbmImplIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/naming/StrategyLegacyHbmImplIntegrationTest.java @@ -1,6 +1,9 @@ -package com.baeldung.naming; +package com.baeldung.boot.naming; + +import com.baeldung.boot.naming.MetadataExtractorIntegrator; +import com.baeldung.boot.naming.NamingConfig.Config; +import com.baeldung.boot.naming.entity.Preference; -import com.baeldung.naming.entity.Preference; import org.assertj.core.api.SoftAssertions; import org.hibernate.boot.Metadata; import org.hibernate.mapping.PersistentClass; @@ -8,6 +11,7 @@ import org.hibernate.mapping.Table; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; @@ -19,6 +23,7 @@ import java.util.Collection; "spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl", "spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl", }) +@Import(Config.class) public class StrategyLegacyHbmImplIntegrationTest extends NamingConfig { @Test diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/repository/UserRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/UserRepositoryIntegrationTest.java similarity index 79% rename from persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/repository/UserRepositoryIntegrationTest.java rename to persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/UserRepositoryIntegrationTest.java index af5abc22d7..8ec1520495 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/repository/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/UserRepositoryIntegrationTest.java @@ -1,12 +1,14 @@ -package com.baeldung.repository; +package com.baeldung.boot.test; -import com.baeldung.domain.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.junit4.SpringRunner; +import com.baeldung.boot.domain.User; +import com.baeldung.boot.repository.UserRepository; + import java.util.Collection; import static org.assertj.core.api.Assertions.assertThat; @@ -24,7 +26,7 @@ public class UserRepositoryIntegrationTest { public void givenTwoImportFilesWhenFindAllShouldReturnSixUsers() { Collection users = userRepository.findAll(); - assertThat(users.size()).isEqualTo(9); + assertThat(users.size()).isEqualTo(3); } } diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java index bcbded95fb..e0678bcf47 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java @@ -41,7 +41,7 @@ public class H2TestProfileJPAConfig { public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); - em.setPackagesToScan(new String[] { "com.baeldung.domain", "com.baeldung.boot.domain" }); + em.setPackagesToScan(new String[] { "com.baeldung.boot.domain" }); em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); em.setJpaProperties(additionalProperties()); return em; diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/application/tests/UserRepositoryIntegrationTest.java similarity index 84% rename from persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java rename to persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/application/tests/UserRepositoryIntegrationTest.java index f27681021e..597628c5d4 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/tests/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/application/tests/UserRepositoryIntegrationTest.java @@ -1,15 +1,17 @@ -package com.baeldung.springbootdatasourceconfig.tests; +package com.baeldung.springbootdatasourceconfig.application.tests; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.springbootdatasourceconfig.application.entities.User; import com.baeldung.springbootdatasourceconfig.application.repositories.UserRepository; -import java.util.List; -import java.util.Optional; -import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; -import static org.assertj.core.api.Assertions.assertThat; -import org.junit.runner.RunWith; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @DataJpaTest @@ -23,6 +25,6 @@ public class UserRepositoryIntegrationTest { userRepository.save(new User("Bob", "bob@domain.com")); List users = (List) userRepository.findAll(); - assertThat(users.size()).isEqualTo(1); + assertThat(users.size()).isEqualTo(3); } } diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java index eb000bbc09..76a4261a24 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java @@ -5,11 +5,14 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.tomcatconnectionpool.application.SpringBootConsoleApplication; + import static org.assertj.core.api.Assertions.*; import org.springframework.boot.test.context.SpringBootTest; @RunWith(SpringRunner.class) -@SpringBootTest +@SpringBootTest(classes = {SpringBootConsoleApplication.class}) public class SpringBootTomcatConnectionPoolIntegrationTest { @Autowired @@ -17,6 +20,6 @@ public class SpringBootTomcatConnectionPoolIntegrationTest { @Test public void givenTomcatConnectionPoolInstance_whenCheckedPoolClassName_thenCorrect() { - assertThat(dataSource.getClass().getName()).isEqualTo("org.apache.tomcat.jdbc.pool.DataSource"); + assertThat(dataSource.getClass().getName()).isEqualTo("com.zaxxer.hikari.HikariDataSource"); } } From a877b0065a6a1635e12ab759c6e7d739c4f9a57a Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 25 Mar 2019 06:35:02 -0600 Subject: [PATCH 450/496] Add jhipster-5 module to parent POM --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index d29824b085..e79e0c5bf3 100644 --- a/pom.xml +++ b/pom.xml @@ -460,6 +460,7 @@ JGit jgroups jhipster + jhipster-5 jib jjwt jmeter @@ -1103,6 +1104,7 @@ JGit jgroups jhipster + jhipster-5 jib jjwt jmeter From fda8a29eb62125705027748ff77fbfba7a2164c3 Mon Sep 17 00:00:00 2001 From: Trevor Gowing Date: Mon, 25 Mar 2019 15:29:04 +0200 Subject: [PATCH 451/496] BAEL-2736 rest assured spring mock mvc (#6466) * Include rest-assured.spring-mock-mvc dependency BAEL-2736 * Rest Assured Spring Mock MVC Tests BAEL-2736 --- testing-modules/rest-assured/pom.xml | 32 +++++++--- .../baeldung/restassured/learner/Course.java | 17 +++++ .../restassured/learner/CourseController.java | 31 +++++++++ .../CourseControllerExceptionHandler.java | 18 ++++++ .../learner/CourseNotFoundException.java | 8 +++ .../restassured/learner/CourseService.java | 27 ++++++++ .../CourseControllerIntegrationTest.java | 40 ++++++++++++ .../learner/CourseControllerUnitTest.java | 63 +++++++++++++++++++ 8 files changed, 226 insertions(+), 10 deletions(-) create mode 100644 testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/Course.java create mode 100644 testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseController.java create mode 100644 testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseControllerExceptionHandler.java create mode 100644 testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseNotFoundException.java create mode 100644 testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseService.java create mode 100644 testing-modules/rest-assured/src/test/java/com/baeldung/restassured/learner/CourseControllerIntegrationTest.java create mode 100644 testing-modules/rest-assured/src/test/java/com/baeldung/restassured/learner/CourseControllerUnitTest.java diff --git a/testing-modules/rest-assured/pom.xml b/testing-modules/rest-assured/pom.xml index 5d3cac4aa3..cd342ccd11 100644 --- a/testing-modules/rest-assured/pom.xml +++ b/testing-modules/rest-assured/pom.xml @@ -19,6 +19,10 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-json + org.springframework.boot spring-boot-starter-test @@ -97,7 +101,7 @@ joda-time - joda-time + joda-time @@ -143,15 +147,6 @@ wiremock ${wiremock.version} - - io.rest-assured - rest-assured - test - - - io.rest-assured - json-schema-validator - com.github.fge json-schema-validator @@ -167,6 +162,23 @@ commons-collections ${commons-collections.version} + + + + io.rest-assured + rest-assured + test + + + io.rest-assured + spring-mock-mvc + test + + + io.rest-assured + json-schema-validator + test + diff --git a/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/Course.java b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/Course.java new file mode 100644 index 0000000000..ac958b3239 --- /dev/null +++ b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/Course.java @@ -0,0 +1,17 @@ +package com.baeldung.restassured.learner; + +class Course { + + private String code; + + public Course() { + } + + Course(String code) { + this.code = code; + } + + String getCode() { + return code; + } +} diff --git a/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseController.java b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseController.java new file mode 100644 index 0000000000..f4a3f56608 --- /dev/null +++ b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseController.java @@ -0,0 +1,31 @@ +package com.baeldung.restassured.learner; + +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 java.util.Collection; + +import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE; + +@RestController +@RequestMapping(path = "/courses") +public class CourseController { + + private final CourseService courseService; + + public CourseController(CourseService courseService) { + this.courseService = courseService; + } + + @GetMapping(produces = APPLICATION_JSON_UTF8_VALUE) + public Collection getCourses() { + return courseService.getCourses(); + } + + @GetMapping(path = "/{code}", produces = APPLICATION_JSON_UTF8_VALUE) + public Course getCourse(@PathVariable String code) { + return courseService.getCourse(code); + } +} diff --git a/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseControllerExceptionHandler.java b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseControllerExceptionHandler.java new file mode 100644 index 0000000000..b17e95c31c --- /dev/null +++ b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseControllerExceptionHandler.java @@ -0,0 +1,18 @@ +package com.baeldung.restassured.learner; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@ControllerAdvice(assignableTypes = CourseController.class) +public class CourseControllerExceptionHandler extends ResponseEntityExceptionHandler { + + @ResponseStatus(HttpStatus.NOT_FOUND) + @ExceptionHandler(CourseNotFoundException.class) + @SuppressWarnings("ThrowablePrintedToSystemOut") + public void handleCourseNotFoundException(CourseNotFoundException cnfe) { + System.out.println(cnfe); + } +} diff --git a/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseNotFoundException.java b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseNotFoundException.java new file mode 100644 index 0000000000..dc1a3f796d --- /dev/null +++ b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseNotFoundException.java @@ -0,0 +1,8 @@ +package com.baeldung.restassured.learner; + +class CourseNotFoundException extends RuntimeException { + + CourseNotFoundException(String code) { + super(code); + } +} diff --git a/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseService.java b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseService.java new file mode 100644 index 0000000000..11508ab9ba --- /dev/null +++ b/testing-modules/rest-assured/src/main/java/com/baeldung/restassured/learner/CourseService.java @@ -0,0 +1,27 @@ +package com.baeldung.restassured.learner; + +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +@Service +class CourseService { + + private static final Map COURSE_MAP = new ConcurrentHashMap<>(); + + static { + Course wizardry = new Course("Wizardry"); + COURSE_MAP.put(wizardry.getCode(), wizardry); + } + + Collection getCourses() { + return COURSE_MAP.values(); + } + + Course getCourse(String code) { + return Optional.ofNullable(COURSE_MAP.get(code)).orElseThrow(() -> new CourseNotFoundException(code)); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/learner/CourseControllerIntegrationTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/learner/CourseControllerIntegrationTest.java new file mode 100644 index 0000000000..5e36cd169b --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/learner/CourseControllerIntegrationTest.java @@ -0,0 +1,40 @@ +package com.baeldung.restassured.learner; + +import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; +import static org.springframework.http.HttpStatus.NOT_FOUND; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.context.WebApplicationContext; + +import io.restassured.module.mockmvc.RestAssuredMockMvc; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = RANDOM_PORT) +public class CourseControllerIntegrationTest { + + @Autowired + private WebApplicationContext webApplicationContext; + + @Before + public void initialiseRestAssuredMockMvcWebApplicationContext() { + RestAssuredMockMvc.webAppContextSetup(webApplicationContext); + } + + @Test + public void givenNoMatchingCourseCodeWhenGetCourseThenRespondWithStatusNotFound() { + String nonMatchingCourseCode = "nonMatchingCourseCode"; + + given() + .when() + .get("/courses/" + nonMatchingCourseCode) + .then() + .log().ifValidationFails() + .statusCode(NOT_FOUND.value()); + } +} diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/learner/CourseControllerUnitTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/learner/CourseControllerUnitTest.java new file mode 100644 index 0000000000..2a795e2b0b --- /dev/null +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/learner/CourseControllerUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung.restassured.learner; + +import io.restassured.module.mockmvc.RestAssuredMockMvc; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.Collections; + +import static io.restassured.http.ContentType.JSON; +import static io.restassured.module.mockmvc.RestAssuredMockMvc.given; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.when; +import static org.springframework.http.HttpStatus.NOT_FOUND; +import static org.springframework.http.HttpStatus.OK; + +@RunWith(MockitoJUnitRunner.class) +public class CourseControllerUnitTest { + + @Mock + private CourseService courseService; + @InjectMocks + private CourseController courseController; + @InjectMocks + private CourseControllerExceptionHandler courseControllerExceptionHandler; + + @Before + public void initialiseRestAssuredMockMvcStandalone() { + RestAssuredMockMvc.standaloneSetup(courseController, courseControllerExceptionHandler); + } + + @Test + public void givenNoExistingCoursesWhenGetCoursesThenRespondWithStatusOkAndEmptyArray() { + when(courseService.getCourses()).thenReturn(Collections.emptyList()); + + given() + .when() + .get("/courses") + .then() + .log().ifValidationFails() + .statusCode(OK.value()) + .contentType(JSON) + .body(is(equalTo("[]"))); + } + + @Test + public void givenNoMatchingCoursesWhenGetCoursesThenRespondWithStatusNotFound() { + String nonMatchingCourseCode = "nonMatchingCourseCode"; + + when(courseService.getCourse(nonMatchingCourseCode)).thenThrow(new CourseNotFoundException(nonMatchingCourseCode)); + + given() + .when() + .get("/courses/" + nonMatchingCourseCode) + .then() + .log().ifValidationFails() + .statusCode(NOT_FOUND.value()); + } +} From 64b8fa049b178d7a24c8145d1b292b0e7b93e2fb Mon Sep 17 00:00:00 2001 From: TINO Date: Mon, 25 Mar 2019 21:58:56 +0300 Subject: [PATCH 452/496] BAEL - 2829 --- .../dao/repositories/PersonRepository.java | 9 +++++ .../PersonRepositoryIntegrationTest.java | 39 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonRepository.java create mode 100644 persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonRepositoryIntegrationTest.java diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonRepository.java new file mode 100644 index 0000000000..c6b75e5994 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.dao.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.domain.Person; + +public interface PersonRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonRepositoryIntegrationTest.java new file mode 100644 index 0000000000..d2e3ac67a0 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonRepositoryIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.dao.repositories; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.domain.Person; + +@RunWith(SpringRunner.class) +@DataJpaTest +public class PersonRepositoryIntegrationTest { + + private static final Person PERSON1 = new Person(1L, "John", "Doe"); + private static final Person PERSON2 = new Person(2L, "Alice", "Bob"); + + @Autowired + private PersonRepository personRepository; + + @Test + public void givenPersonEntity_whenInsertWithSave_ThenPersonIsPersisted() { + personRepository.save(PERSON1); + assertPersonPersisted(PERSON1); + } + + @Test + public void givenPersonEntity_whenInsertWithSaveAndFlush_ThenPersonIsPersisted() { + personRepository.saveAndFlush(PERSON2); + assertPersonPersisted(PERSON2); + } + + private void assertPersonPersisted(Person input) { + Person person = personRepository.getOne(input.getId()); + assertThat(person).isNotNull(); + } +} From 52587443de5659264789b8bbb81f532969d57bcb Mon Sep 17 00:00:00 2001 From: Krzysiek Date: Mon, 25 Mar 2019 21:15:34 +0100 Subject: [PATCH 453/496] BAEL-2836 Mediator Pattern in Java --- .../java/com/baeldung/mediator/Button.java | 13 +++++++ .../main/java/com/baeldung/mediator/Fan.java | 24 ++++++++++++ .../java/com/baeldung/mediator/Mediator.java | 37 +++++++++++++++++++ .../com/baeldung/mediator/PowerSupplier.java | 11 ++++++ .../com/baeldung/mediator/ButtonTest.java | 36 ++++++++++++++++++ 5 files changed, 121 insertions(+) create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Button.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Fan.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Mediator.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/mediator/PowerSupplier.java create mode 100644 patterns/design-patterns-2/src/test/java/com/baeldung/mediator/ButtonTest.java diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Button.java b/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Button.java new file mode 100644 index 0000000000..0507d27872 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Button.java @@ -0,0 +1,13 @@ +package com.baeldung.mediator; + +public class Button { + private Mediator mediator; + + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + public void press() { + this.mediator.press(); + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Fan.java b/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Fan.java new file mode 100644 index 0000000000..b7862f42d5 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Fan.java @@ -0,0 +1,24 @@ +package com.baeldung.mediator; + +public class Fan { + private Mediator mediator; + private boolean isOn = false; + + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + public boolean isOn() { + return isOn; + } + + public void turnOn() { + this.mediator.start(); + isOn = true; + } + + public void turnOff() { + isOn = false; + this.mediator.stop(); + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Mediator.java b/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Mediator.java new file mode 100644 index 0000000000..08cd023748 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/Mediator.java @@ -0,0 +1,37 @@ +package com.baeldung.mediator; + +public class Mediator { + private Button button; + private Fan fan; + private PowerSupplier powerSupplier; + + public void setButton(Button button) { + this.button = button; + this.button.setMediator(this); + } + + public void setFan(Fan fan) { + this.fan = fan; + this.fan.setMediator(this); + } + + public void setPowerSupplier(PowerSupplier powerSupplier) { + this.powerSupplier = powerSupplier; + } + + public void press() { + if (fan.isOn()) { + fan.turnOff(); + } else { + fan.turnOn(); + } + } + + public void start() { + powerSupplier.turnOn(); + } + + public void stop() { + powerSupplier.turnOff(); + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/PowerSupplier.java b/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/PowerSupplier.java new file mode 100644 index 0000000000..b4a05816c7 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/mediator/PowerSupplier.java @@ -0,0 +1,11 @@ +package com.baeldung.mediator; + +public class PowerSupplier { + public void turnOn() { + // implementation + } + + public void turnOff() { + // implementation + } +} diff --git a/patterns/design-patterns-2/src/test/java/com/baeldung/mediator/ButtonTest.java b/patterns/design-patterns-2/src/test/java/com/baeldung/mediator/ButtonTest.java new file mode 100644 index 0000000000..837682d880 --- /dev/null +++ b/patterns/design-patterns-2/src/test/java/com/baeldung/mediator/ButtonTest.java @@ -0,0 +1,36 @@ +package com.baeldung.mediator; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class ButtonTest { + + private Button button; + private Fan fan; + + @Before + public void setUp() { + this.button = new Button(); + this.fan = new Fan(); + PowerSupplier powerSupplier = new PowerSupplier(); + Mediator mediator = new Mediator(); + + mediator.setButton(this.button); + mediator.setFan(fan); + mediator.setPowerSupplier(powerSupplier); + } + + @Test + public void givenTurnedOffFan_whenPressingButtonTwice_fanShouldTurnOnAndOff() { + assertFalse(fan.isOn()); + + button.press(); + assertTrue(fan.isOn()); + + button.press(); + assertFalse(fan.isOn()); + } +} \ No newline at end of file From 6461816289bd27111d34e0dbca04d859f0df889e Mon Sep 17 00:00:00 2001 From: Krzysiek Date: Mon, 25 Mar 2019 21:34:06 +0100 Subject: [PATCH 454/496] BAEL-2836 jUnit test class name fix --- .../mediator/{ButtonTest.java => MediatorIntegrationTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename patterns/design-patterns-2/src/test/java/com/baeldung/mediator/{ButtonTest.java => MediatorIntegrationTest.java} (95%) diff --git a/patterns/design-patterns-2/src/test/java/com/baeldung/mediator/ButtonTest.java b/patterns/design-patterns-2/src/test/java/com/baeldung/mediator/MediatorIntegrationTest.java similarity index 95% rename from patterns/design-patterns-2/src/test/java/com/baeldung/mediator/ButtonTest.java rename to patterns/design-patterns-2/src/test/java/com/baeldung/mediator/MediatorIntegrationTest.java index 837682d880..0bda659f3f 100644 --- a/patterns/design-patterns-2/src/test/java/com/baeldung/mediator/ButtonTest.java +++ b/patterns/design-patterns-2/src/test/java/com/baeldung/mediator/MediatorIntegrationTest.java @@ -6,7 +6,7 @@ import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class ButtonTest { +public class MediatorIntegrationTest { private Button button; private Fan fan; From 970a94bc760f683419073083acec3e5640e506a0 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 25 Mar 2019 21:32:17 -0600 Subject: [PATCH 455/496] Create jhipster-5 POM --- jhipster-5/pom.xml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 jhipster-5/pom.xml diff --git a/jhipster-5/pom.xml b/jhipster-5/pom.xml new file mode 100644 index 0000000000..df60b01317 --- /dev/null +++ b/jhipster-5/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + com.baeldung.jhipster + jhipster-5 + 1.0.0-SNAPSHOT + JHipster + pom + + + parent-boot-1 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-1 + + + + bookstore-monolith + + + From 1860c47a701fe666aa7e1a6dd5df926149667e9e Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Tue, 26 Mar 2019 15:23:56 +0800 Subject: [PATCH 456/496] Update README.md --- jackson-2/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jackson-2/README.md b/jackson-2/README.md index 7c14bcfd19..ec147f5fd9 100644 --- a/jackson-2/README.md +++ b/jackson-2/README.md @@ -6,4 +6,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [Mapping Multiple JSON Fields to One Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) \ No newline at end of file +- [Mapping Multiple JSON Fields to a Single Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) From 0b70193fd8d6c186a5ed8016654ec8c80ada0629 Mon Sep 17 00:00:00 2001 From: zbikenson Date: Tue, 26 Mar 2019 19:16:49 +0000 Subject: [PATCH 457/496] BAEL-2769 Added MockK examples --- kotlin-libraries/pom.xml | 27 ++++++ .../baeldung/mockk/AnnotationMockKUnitTest.kt | 44 +++++++++ .../com/baeldung/mockk/BasicMockKUnitTest.kt | 92 +++++++++++++++++++ .../mockk/HierarchicalMockKUnitTest.kt | 33 +++++++ .../com/baeldung/mockk/TestableService.kt | 12 +++ 5 files changed, 208 insertions(+) create mode 100644 kotlin-libraries/src/test/kotlin/com/baeldung/mockk/AnnotationMockKUnitTest.kt create mode 100644 kotlin-libraries/src/test/kotlin/com/baeldung/mockk/BasicMockKUnitTest.kt create mode 100644 kotlin-libraries/src/test/kotlin/com/baeldung/mockk/HierarchicalMockKUnitTest.kt create mode 100644 kotlin-libraries/src/test/kotlin/com/baeldung/mockk/TestableService.kt diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml index e3f69b4ea9..3d2c7337b0 100644 --- a/kotlin-libraries/pom.xml +++ b/kotlin-libraries/pom.xml @@ -140,6 +140,32 @@ kotlinx-collections-immutable 0.1 + + + + io.mockk + mockk + ${mockk.version} + test + + + net.bytebuddy + byte-buddy + 1.8.13 + compile + + + net.bytebuddy + byte-buddy-agent + 1.8.13 + compile + + + org.objenesis + objenesis + 2.6 + compile + @@ -154,6 +180,7 @@ 3.10.0 1.4.197 0.10.4 + 1.9.3 diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/AnnotationMockKUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/AnnotationMockKUnitTest.kt new file mode 100644 index 0000000000..56cd8b43eb --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/AnnotationMockKUnitTest.kt @@ -0,0 +1,44 @@ +package com.baeldung.mockk + +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.InjectMockKs +import io.mockk.impl.annotations.MockK +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class InjectTestService { + lateinit var service1: TestableService + lateinit var service2: TestableService + + fun invokeService1(): String { + return service1.getDataFromDb("Test Param") + } +} + +class AnnotationMockKUnitTest { + + @MockK + lateinit var service1: TestableService + + @MockK + lateinit var service2: TestableService + + @InjectMockKs + var objectUnderTest = InjectTestService() + + @BeforeEach + fun setUp() = MockKAnnotations.init(this) + + @Test + fun givenServiceMock_whenCallingMockedMethod_thenCorrectlyVerified() { + // given + every { service1.getDataFromDb("Test Param") } returns "No" + // when + val result = objectUnderTest.invokeService1() + // then + assertEquals("No", result) + } + +} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/BasicMockKUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/BasicMockKUnitTest.kt new file mode 100644 index 0000000000..df4c03be09 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/BasicMockKUnitTest.kt @@ -0,0 +1,92 @@ +package com.baeldung.mockk + +import io.mockk.* +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + + +class BasicMockKUnitTest { + + @Test + fun givenServiceMock_whenCallingMockedMethod_thenCorrectlyVerified() { + // given + val service = mockk() + every { service.getDataFromDb("Expected Param") } returns "Expected Output" + // when + val result = service.getDataFromDb("Expected Param") + // then + verify { service.getDataFromDb("Expected Param") } + assertEquals("Expected Output", result) + } + + @Test + fun givenServiceSpy_whenMockingOnlyOneMethod_thenOtherMethodsShouldBehaveAsOriginalObject() { + // given + val service = spyk() + every { service.getDataFromDb(any()) } returns "Mocked Output" + // when checking mocked method + val firstResult = service.getDataFromDb("Any Param") + // then + assertEquals("Mocked Output", firstResult) + // when checking not mocked method + val secondResult = service.doSomethingElse("Any Param") + // then + assertEquals("I don't want to!", secondResult) + } + + @Test + fun givenRelaxedMock_whenCallingNotMockedMethod_thenReturnDefaultValue() { + // given + val service = mockk(relaxed = true) + // when + val result = service.getDataFromDb("Any Param") + // then + assertEquals("", result) + } + + @Test + fun givenObject_whenMockingIt_thenMockedMethodShouldReturnProperValue() { + // given + val service = TestableService() + mockkObject(service) + // when calling not mocked method + val firstResult = service.getDataFromDb("Any Param") + // then return real response + assertEquals("Value from DB", firstResult) + + // when calling mocked method + every { service.getDataFromDb(any()) } returns "Mocked Output" + val secondResult = service.getDataFromDb("Any Param") + // then return mocked response + assertEquals("Mocked Output", secondResult) + } + + @Test + fun givenMock_whenCapturingParamValue_thenProperValueShouldBeCaptured() { + // given + val service = mockk() + val slot = slot() + every { service.getDataFromDb(capture(slot)) } returns "Expected Output" + // when + service.getDataFromDb("Expected Param") + // then + assertEquals("Expected Param", slot.captured) + } + + @Test + fun givenMock_whenCapturingParamsValues_thenProperValuesShouldBeCaptured() { + // given + val service = mockk() + val list = mutableListOf() + every { service.getDataFromDb(capture(list)) } returns "Expected Output" + // when + service.getDataFromDb("Expected Param 1") + service.getDataFromDb("Expected Param 2") + // then + assertEquals(2, list.size) + assertEquals("Expected Param 1", list[0]) + assertEquals("Expected Param 2", list[1]) + } + + +} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/HierarchicalMockKUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/HierarchicalMockKUnitTest.kt new file mode 100644 index 0000000000..e9ef133663 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/HierarchicalMockKUnitTest.kt @@ -0,0 +1,33 @@ +package com.baeldung.mockk + +import io.mockk.* +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class Foo { + lateinit var name: String + lateinit var bar: Bar +} + +class Bar { + lateinit var nickname: String +} + +class HierarchicalMockKUnitTest { + + @Test + fun givenHierarchicalClass_whenMockingIt_thenReturnProperValue() { + // given + val foo = mockk { + every { name } returns "Karol" + every { bar } returns mockk { + every { nickname } returns "Tomato" + } + } + // when + val result = foo.bar.nickname + // then + assertEquals("Tomato", result) + } + +} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/TestableService.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/TestableService.kt new file mode 100644 index 0000000000..d6f57e5fb0 --- /dev/null +++ b/kotlin-libraries/src/test/kotlin/com/baeldung/mockk/TestableService.kt @@ -0,0 +1,12 @@ +package com.baeldung.mockk + +class TestableService { + fun getDataFromDb(testParameter: String): String { + // query database and return matching value + return "Value from DB" + } + + fun doSomethingElse(testParameter: String): String { + return "I don't want to!" + } +} \ No newline at end of file From 07b62fd912225f70f8d267b8c5a9439834427ad7 Mon Sep 17 00:00:00 2001 From: beardyinc <43503240+beardyinc@users.noreply.github.com> Date: Wed, 27 Mar 2019 03:41:42 +0100 Subject: [PATCH 458/496] BAEl 2803 (#6574) * BAEL-2803 Sample Code * updated tests, repo method names * moved sources for BAEL-2803 here * removed dependencies introduced by BAEL-2803 * re-added sources * renamed test methods according to BDD --- .../main/java/com/baeldung/exists/Car.java | 48 +++++++++++ .../com/baeldung/exists/CarRepository.java | 24 ++++++ .../exists/CarRepositoryIntegrationTest.java | 86 +++++++++++++++++++ spring-boot-data/pom.xml | 2 +- 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/Car.java create mode 100644 persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/CarRepository.java create mode 100644 persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/Car.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/Car.java new file mode 100644 index 0000000000..bf09caf6ff --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/Car.java @@ -0,0 +1,48 @@ +package com.baeldung.exists; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +/** + * @author paullatzelsperger + * @since 2019-03-20 + */ +@Entity +public class Car { + + @Id + @GeneratedValue + private int id; + private Integer power; + private String model; + + Car() { + + } + + public Car(int power, String model) { + this.power = power; + this.model = model; + } + + public Integer getPower() { + return power; + } + + public void setPower(Integer power) { + this.power = power; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public int getId() { + return id; + } +} diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/CarRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/CarRepository.java new file mode 100644 index 0000000000..a54f19f4cd --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/CarRepository.java @@ -0,0 +1,24 @@ +package com.baeldung.exists; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +/** + * @author paullatzelsperger + * @since 2019-03-20 + */ +@Repository +public interface CarRepository extends JpaRepository { + + boolean existsCarByPower(int power); + + boolean existsCarByModel(String model); + + @Query("select case when count(c)> 0 then true else false end from Car c where c.model = :model") + boolean existsCarExactCustomQuery(@Param("model") String model); + + @Query("select case when count(c)> 0 then true else false end from Car c where lower(c.model) like lower(:model)") + boolean existsCarLikeCustomQuery(@Param("model") String model); +} diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java new file mode 100644 index 0000000000..1633df35d6 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java @@ -0,0 +1,86 @@ +package com.baeldung.exists; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.ignoreCase; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Example; +import org.springframework.data.domain.ExampleMatcher; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Arrays; +import java.util.List; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class CarRepositoryIntegrationTest { + + @Autowired + private CarRepository repository; + private int searchId; + + @Before + public void setup() { + List cars = repository.saveAll(Arrays.asList(new Car(200, "BMW"), new Car(300, "Audi"))); + searchId = cars.get(0).getId(); + } + + @After + public void teardown() { + repository.deleteAll(); + } + + @Test + public void whenIdIsCorrect_thenExistsShouldReturnTrue() { + assertThat(repository.existsById(searchId)).isTrue(); + } + + @Test + public void givenExample_whenExists_thenIsTrue() { + ExampleMatcher modelMatcher = ExampleMatcher.matching() + .withIgnorePaths("id") // must explicitly ignore -> PK + .withMatcher("model", ignoreCase()); + Car probe = new Car(); + probe.setModel("bmw"); + + Example example = Example.of(probe, modelMatcher); + + assertThat(repository.exists(example)).isTrue(); + } + + @Test + public void givenPower_whenExists_thenIsFalse() { + assertThat(repository.existsCarByPower(200)).isTrue(); + assertThat(repository.existsCarByPower(800)).isFalse(); + } + + @Test + public void existsByDerivedQuery_byModel() { + assertThat(repository.existsCarByModel("Audi")).isTrue(); + assertThat(repository.existsCarByModel("audi")).isFalse(); + assertThat(repository.existsCarByModel("AUDI")).isFalse(); + assertThat(repository.existsCarByModel("")).isFalse(); + } + + @Test + public void givenModelName_whenExistsExact_thenIsTrue() { + assertThat(repository.existsCarExactCustomQuery("BMW")).isTrue(); + assertThat(repository.existsCarExactCustomQuery("Bmw")).isFalse(); + assertThat(repository.existsCarExactCustomQuery("bmw")).isFalse(); + assertThat(repository.existsCarExactCustomQuery("")).isFalse(); + } + + @Test + public void givenModelName_whenExistsLike_thenIsTrue() { + assertThat(repository.existsCarLikeCustomQuery("BMW")).isTrue(); + assertThat(repository.existsCarLikeCustomQuery("Bmw")).isTrue(); + assertThat(repository.existsCarLikeCustomQuery("bmw")).isTrue(); + assertThat(repository.existsCarLikeCustomQuery("")).isFalse(); + } + +} diff --git a/spring-boot-data/pom.xml b/spring-boot-data/pom.xml index 9ef4cc69c8..8735a54e7b 100644 --- a/spring-boot-data/pom.xml +++ b/spring-boot-data/pom.xml @@ -119,4 +119,4 @@ 2.2.4 - \ No newline at end of file + From e506bc1d75ba288c2a241961f975ae131c2c0f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Felipe=20Pizzolotto=20Bini?= Date: Wed, 27 Mar 2019 13:35:58 -0300 Subject: [PATCH 459/496] fix sonar issues (#6394) --- .../config/ForkJoinStateMachineConfiguration.java | 4 ++-- .../config/JunctionStateMachineConfiguration.java | 4 ++-- .../config/SimpleStateMachineConfiguration.java | 4 ++-- .../statemachine/config/StateMachineListener.java | 4 ++-- .../ForkJoinStateMachineIntegrationTest.java | 3 --- .../HierarchicalStateMachineIntegrationTest.java | 3 --- .../JunctionStateMachineIntegrationTest.java | 4 ---- .../StateEnumMachineIntegrationTest.java | 4 ---- .../StateMachineBuilderIntegrationTest.java | 4 ++-- .../statemachine/StateMachineIntegrationTest.java | 13 ++++--------- 10 files changed, 14 insertions(+), 33 deletions(-) diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java index 3a3e632c51..55e1397823 100644 --- a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/ForkJoinStateMachineConfiguration.java @@ -64,11 +64,11 @@ public class ForkJoinStateMachineConfiguration extends StateMachineConfigurerAda @Bean public Guard mediumGuard() { - return (ctx) -> false; + return ctx -> false; } @Bean public Guard highGuard() { - return (ctx) -> false; + return ctx -> false; } } \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java index 2f48a9dbb5..21b37381df 100644 --- a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/JunctionStateMachineConfiguration.java @@ -50,11 +50,11 @@ public class JunctionStateMachineConfiguration extends StateMachineConfigurerAda @Bean public Guard mediumGuard() { - return (ctx) -> false; + return ctx -> false; } @Bean public Guard highGuard() { - return (ctx) -> false; + return ctx -> false; } } \ No newline at end of file diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java index d1b1ce001c..0c392c2c35 100644 --- a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/SimpleStateMachineConfiguration.java @@ -18,7 +18,7 @@ import java.util.logging.Logger; @EnableStateMachine public class SimpleStateMachineConfiguration extends StateMachineConfigurerAdapter { - public static final Logger LOGGER = Logger.getLogger(SimpleStateMachineConfiguration.class.getName()); + private static final Logger LOGGER = Logger.getLogger(SimpleStateMachineConfiguration.class.getName()); @Override public void configure(StateMachineConfigurationConfigurer config) throws Exception { @@ -80,7 +80,7 @@ public class SimpleStateMachineConfiguration extends StateMachineConfigurerAdapt @Bean public Guard simpleGuard() { - return (ctx) -> { + return ctx -> { int approvalCount = (int) ctx .getExtendedState() .getVariables() diff --git a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java index 47a274404e..09e8946810 100644 --- a/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java +++ b/spring-state-machine/src/main/java/com/baeldung/spring/statemachine/config/StateMachineListener.java @@ -7,10 +7,10 @@ import java.util.logging.Logger; public class StateMachineListener extends StateMachineListenerAdapter { - public static final Logger LOGGER = Logger.getLogger(StateMachineListener.class.getName()); + private static final Logger LOGGER = Logger.getLogger(StateMachineListener.class.getName()); @Override public void stateChanged(State from, State to) { - LOGGER.info(String.format("Transitioned from %s to %s%n", from == null ? "none" : from.getId(), to.getId())); + LOGGER.info(() -> String.format("Transitioned from %s to %s%n", from == null ? "none" : from.getId(), to.getId())); } } diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineIntegrationTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineIntegrationTest.java index b34d5c47c6..66acad901c 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineIntegrationTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineIntegrationTest.java @@ -1,18 +1,15 @@ package com.baeldung.spring.statemachine; import com.baeldung.spring.statemachine.config.ForkJoinStateMachineConfiguration; -import com.baeldung.spring.statemachine.config.JunctionStateMachineConfiguration; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.statemachine.StateMachine; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import javax.annotation.Resource; import java.util.Arrays; import static org.junit.Assert.assertEquals; diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineIntegrationTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineIntegrationTest.java index 3d7c0be828..00a9c9a08c 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineIntegrationTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineIntegrationTest.java @@ -1,18 +1,15 @@ package com.baeldung.spring.statemachine; import com.baeldung.spring.statemachine.config.HierarchicalStateMachineConfiguration; -import com.baeldung.spring.statemachine.config.JunctionStateMachineConfiguration; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.statemachine.StateMachine; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import javax.annotation.Resource; import java.util.Arrays; import static org.junit.Assert.assertEquals; diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineIntegrationTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineIntegrationTest.java index 93de23fad3..f0ee757522 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineIntegrationTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineIntegrationTest.java @@ -1,20 +1,16 @@ package com.baeldung.spring.statemachine; import com.baeldung.spring.statemachine.config.JunctionStateMachineConfiguration; -import com.baeldung.spring.statemachine.config.SimpleEnumStateMachineConfiguration; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.statemachine.StateMachine; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import javax.annotation.Resource; - @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = JunctionStateMachineConfiguration.class) public class JunctionStateMachineIntegrationTest { diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineIntegrationTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineIntegrationTest.java index 9074ece001..d345cd0dfc 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineIntegrationTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineIntegrationTest.java @@ -3,19 +3,15 @@ package com.baeldung.spring.statemachine; import com.baeldung.spring.statemachine.applicationreview.ApplicationReviewEvents; import com.baeldung.spring.statemachine.applicationreview.ApplicationReviewStates; import com.baeldung.spring.statemachine.config.SimpleEnumStateMachineConfiguration; -import com.baeldung.spring.statemachine.config.SimpleStateMachineConfiguration; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.statemachine.StateMachine; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import javax.annotation.Resource; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderIntegrationTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderIntegrationTest.java index c1de8b8958..e5431d9d83 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderIntegrationTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineBuilderIntegrationTest.java @@ -1,11 +1,11 @@ package com.baeldung.spring.statemachine; -import static org.junit.Assert.assertEquals; - import org.junit.Test; import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.config.StateMachineBuilder; +import static org.junit.Assert.assertEquals; + public class StateMachineBuilderIntegrationTest { @Test diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineIntegrationTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineIntegrationTest.java index 25df7c8cd3..aab07225a3 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineIntegrationTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateMachineIntegrationTest.java @@ -1,22 +1,17 @@ package com.baeldung.spring.statemachine; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - +import com.baeldung.spring.statemachine.config.SimpleStateMachineConfiguration; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.statemachine.StateMachine; - -import com.baeldung.spring.statemachine.config.SimpleStateMachineConfiguration; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.junit4.SpringRunner; -import javax.annotation.Resource; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SimpleStateMachineConfiguration.class) @@ -42,7 +37,7 @@ public class StateMachineIntegrationTest { } @Test - public void whenSimpleStringMachineActionState_thenActionExecuted() throws InterruptedException { + public void whenSimpleStringMachineActionState_thenActionExecuted() { stateMachine.sendEvent("E3"); assertEquals("S3", stateMachine.getState().getId()); From 65ae0ce3c48cb4550ea74321239a823c70e7c0aa Mon Sep 17 00:00:00 2001 From: Dave Crane Date: Wed, 27 Mar 2019 16:40:56 +0000 Subject: [PATCH 460/496] Bael 2712 lombok builder singular (#6435) * updated lombok libs to 1.18.4 * sketched out basic test class for @singular * more examples showing other collection types, non-standard plural * fixed indentation --- .../lombok/builder/singular/Person.java | 25 +++ .../baeldung/lombok/builder/singular/Sea.java | 14 ++ ...SingularSupportForCollectionsUnitTest.java | 192 ++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 lombok/src/main/java/com/baeldung/lombok/builder/singular/Person.java create mode 100644 lombok/src/main/java/com/baeldung/lombok/builder/singular/Sea.java create mode 100644 lombok/src/test/java/com/baeldung/lombok/builder/singular/BuilderWithSingularSupportForCollectionsUnitTest.java diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/singular/Person.java b/lombok/src/main/java/com/baeldung/lombok/builder/singular/Person.java new file mode 100644 index 0000000000..d7d95feb66 --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/singular/Person.java @@ -0,0 +1,25 @@ +package com.baeldung.lombok.builder.singular; + +import lombok.Builder; +import lombok.Getter; +import lombok.Singular; + +import java.time.LocalDate; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@Getter +@Builder +public class Person { + + private final String givenName; + private final String additionalName; + private final String familyName; + + private final List tags; + @Singular private final List interests; + @Singular private final Set skills; + @Singular private final Map awards; +} diff --git a/lombok/src/main/java/com/baeldung/lombok/builder/singular/Sea.java b/lombok/src/main/java/com/baeldung/lombok/builder/singular/Sea.java new file mode 100644 index 0000000000..8cf38e5f1a --- /dev/null +++ b/lombok/src/main/java/com/baeldung/lombok/builder/singular/Sea.java @@ -0,0 +1,14 @@ +package com.baeldung.lombok.builder.singular; + +import java.util.List; +import lombok.Builder; +import lombok.Getter; +import lombok.Singular; + +@Getter +@Builder +public class Sea { + + @Singular private final List grasses; + @Singular("oneFish") private final List fish; +} diff --git a/lombok/src/test/java/com/baeldung/lombok/builder/singular/BuilderWithSingularSupportForCollectionsUnitTest.java b/lombok/src/test/java/com/baeldung/lombok/builder/singular/BuilderWithSingularSupportForCollectionsUnitTest.java new file mode 100644 index 0000000000..41d5b19df7 --- /dev/null +++ b/lombok/src/test/java/com/baeldung/lombok/builder/singular/BuilderWithSingularSupportForCollectionsUnitTest.java @@ -0,0 +1,192 @@ +package com.baeldung.lombok.builder.singular; + +import org.junit.Test; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class BuilderWithSingularSupportForCollectionsUnitTest { + + @Test + public void canAddMultipleElementsAsNewCollection() throws Exception { + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .tags(Arrays.asList("fictional", "incidental")) + .build(); + + assertThat(person.getTags(), containsInAnyOrder("fictional", "incidental")); + } + + @Test + public void canUpdateCollectionAfterBuildIfMutableCollectionPassedToBuilder() throws Exception { + + List tags = new ArrayList(); + tags.add("fictional"); + tags.add("incidental"); + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .tags(tags) + .build(); + person.getTags() + .clear(); + person.getTags() + .add("non-fictional"); + person.getTags() + .add("important"); + + assertThat(person.getTags(), containsInAnyOrder("non-fictional", "important")); + } + + @Test(expected = UnsupportedOperationException.class) + public void cannotUpdateCollectionAfterBuildIfImmutableCollectionPassedToBuilder() throws Exception { + List tags = Arrays.asList("fictional", "incidental"); + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .tags(tags) + .build(); + person.getTags() + .clear(); + } + + @Test + public void canAssignToSingularAnnotatedCollectionOneByOne() throws Exception { + + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .interest("history") + .interest("sport") + .build(); + + assertThat(person.getInterests(), containsInAnyOrder("sport", "history")); + } + + @Test(expected = UnsupportedOperationException.class) + public void singularAnnotatedBuilderCreatesImmutableCollection() throws Exception { + + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .interest("history") + .interest("sport") + .build(); + person.getInterests() + .clear(); + } + + @Test + public void unpopulatedListsCreatedAsNullIfNotSingularButEmptyArrayIfSingular() throws Exception { + + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .build(); + assertThat(person.getInterests(), hasSize(0)); + assertThat(person.getSkills(), hasSize(0)); + assertThat(person.getAwards() + .keySet(), hasSize(0)); + assertThat(person.getTags(), is(nullValue())); + } + + @Test + public void singularSupportsSetsToo() throws Exception { + + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .skill("singing") + .skill("dancing") + .build(); + assertThat(person.getSkills(), contains("singing", "dancing")); + } + + @Test + public void singularSetsAreLenientWithDuplicates() throws Exception { + + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .interest("singing") + .interest("singing") + .skill("singing") + .skill("singing") + .build(); + assertThat(person.getInterests(), contains("singing", "singing")); + assertThat(person.getSkills(), contains("singing")); + } + + @Test + public void singularSupportsMapsToo() throws Exception { + + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .award("Singer of the Year", LocalDate.now() + .minusYears(5)) + .award("Best Dancer", LocalDate.now() + .minusYears(2)) + .build(); + assertThat(person.getAwards() + .keySet(), contains("Singer of the Year", "Best Dancer")); + assertThat(person.getAwards() + .get("Best Dancer"), + is(LocalDate.now() + .minusYears(2))); + } + + @Test + public void singularIsLenientWithMapKeys() throws Exception { + + Person person = Person.builder() + .givenName("Aaron") + .additionalName("A") + .familyName("Aardvark") + .award("Best Dancer", LocalDate.now() + .minusYears(5)) + .award("Best Dancer", LocalDate.now() + .minusYears(4)) + .award("Best Dancer", LocalDate.now() + .minusYears(3)) + .award("Best Dancer", LocalDate.now() + .minusYears(2)) + .award("Best Dancer", LocalDate.now() + .minusYears(1)) + .build(); + assertThat(person.getAwards() + .keySet(), hasSize(1)); + assertThat(person.getAwards() + .get("Best Dancer"), + is(LocalDate.now() + .minusYears(1))); + } + + @Test + public void wordsWithNonStandardPlurals() throws Exception { + Sea sea = Sea.builder() + .grass("Dulse") + .grass("Kelp") + .oneFish("Cod") + .oneFish("Mackerel") + .build(); + assertThat(sea.getGrasses(), contains("Dulse", "Kelp")); + assertThat(sea.getFish(), contains("Cod", "Mackerel")); + } + +} From fc8abdc6e340032e8b29e203660ff49bade16121 Mon Sep 17 00:00:00 2001 From: Guilherme Humberto Jansen Date: Wed, 27 Mar 2019 13:56:59 -0300 Subject: [PATCH 461/496] Fix for Issue #6594. https://github.com/eugenp/tutorials/issues/6594 (#6595) --- spring-boot-angular-ecommerce/src/main/frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-angular-ecommerce/src/main/frontend/package.json b/spring-boot-angular-ecommerce/src/main/frontend/package.json index 958e9f1023..17363ef961 100644 --- a/spring-boot-angular-ecommerce/src/main/frontend/package.json +++ b/spring-boot-angular-ecommerce/src/main/frontend/package.json @@ -7,7 +7,7 @@ "build": "ng build", "postbuild": "npm run deploy", "predeploy": "rimraf ../resources/static/ && mkdirp ../resources/static", - "deploy": "copyfiles -f dist/** ../resources/static", + "deploy": "copyfiles -f dist/frontend/** ../resources/static", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" From d26f3ac49a176a193768830bcd2797739c42255a Mon Sep 17 00:00:00 2001 From: isaolmez Date: Wed, 27 Mar 2019 21:35:54 +0300 Subject: [PATCH 462/496] BAEL-2715: Moved reactor netty samples to an existing module --- spring-5-webflux/pom.xml | 25 +++----- .../CustomNettyWebServerFactory.java | 36 +++++++++++ .../serverconfig/GreetingController.java | 23 +++++++ .../spring/serverconfig/GreetingService.java | 12 ++++ .../NettyWebServerFactoryPortCustomizer.java | 30 +++++++++ .../NettyWebServerFactorySslCustomizer.java | 26 ++++++++ .../serverconfig/ServerConfigApplication.java | 12 ++++ .../src/main/resources/logback.xml | 31 ++++++++++ .../src/main/resources/sample.jks | Bin 0 -> 2264 bytes ... => ResponseStatusControllerLiveTest.java} | 2 +- .../GreetingControllerIntegrationTest.java | 41 +++++++++++++ .../spring/serverconfig/GreetingLiveTest.java | 57 ++++++++++++++++++ .../GreetingSkipAutoConfigLiveTest.java | 8 +++ .../src/test/resources/logback-test.xml | 13 ++++ 14 files changed, 299 insertions(+), 17 deletions(-) create mode 100644 spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/CustomNettyWebServerFactory.java create mode 100644 spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/GreetingController.java create mode 100644 spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/GreetingService.java create mode 100644 spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactoryPortCustomizer.java create mode 100644 spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java create mode 100644 spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/ServerConfigApplication.java create mode 100644 spring-5-webflux/src/main/resources/logback.xml create mode 100644 spring-5-webflux/src/main/resources/sample.jks rename spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/{ResponseStatusControllerTests.java => ResponseStatusControllerLiveTest.java} (97%) create mode 100644 spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingControllerIntegrationTest.java create mode 100644 spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingLiveTest.java create mode 100644 spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingSkipAutoConfigLiveTest.java create mode 100644 spring-5-webflux/src/test/resources/logback-test.xml diff --git a/spring-5-webflux/pom.xml b/spring-5-webflux/pom.xml index d7fb7b7930..3306fd1729 100644 --- a/spring-5-webflux/pom.xml +++ b/spring-5-webflux/pom.xml @@ -1,23 +1,20 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.baeldung spring-5-webflux 1.0-SNAPSHOT - spring-5-webflux - http://www.baeldung.com - - UTF-8 - 1.8 - 1.8 - 2.0.2.RELEASE - + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + @@ -58,12 +55,8 @@ - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 + org.springframework.boot + spring-boot-maven-plugin diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/CustomNettyWebServerFactory.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/CustomNettyWebServerFactory.java new file mode 100644 index 0000000000..f9de3b4006 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/CustomNettyWebServerFactory.java @@ -0,0 +1,36 @@ +package com.baeldung.spring.serverconfig; + +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import reactor.netty.http.server.HttpServer; + +@Configuration +@Profile("skipAutoConfig") +public class CustomNettyWebServerFactory { + + @Bean + public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() { + NettyReactiveWebServerFactory webServerFactory = new NettyReactiveWebServerFactory(); + webServerFactory.addServerCustomizers(new EventLoopNettyCustomizer()); + return webServerFactory; + } + + private static class EventLoopNettyCustomizer implements NettyServerCustomizer { + + @Override + public HttpServer apply(HttpServer httpServer) { + EventLoopGroup parentGroup = new NioEventLoopGroup(); + EventLoopGroup childGroup = new NioEventLoopGroup(); + return httpServer + .tcpConfiguration(tcpServer -> tcpServer.bootstrap( + serverBootstrap -> serverBootstrap.group(parentGroup, childGroup).channel(NioServerSocketChannel.class) + )); + } + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/GreetingController.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/GreetingController.java new file mode 100644 index 0000000000..990ea5cf83 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/GreetingController.java @@ -0,0 +1,23 @@ +package com.baeldung.spring.serverconfig; + +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 reactor.core.publisher.Mono; + +@RestController +@RequestMapping("/greet") +public class GreetingController { + + private final GreetingService greetingService; + + public GreetingController(GreetingService greetingService) { + this.greetingService = greetingService; + } + + @GetMapping("/{name}") + private Mono greet(@PathVariable String name) { + return greetingService.greet(name); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/GreetingService.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/GreetingService.java new file mode 100644 index 0000000000..a6243b2bd0 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/GreetingService.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.serverconfig; + +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Service +public class GreetingService { + + public Mono greet(String name) { + return Mono.just("Greeting " + name); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactoryPortCustomizer.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactoryPortCustomizer.java new file mode 100644 index 0000000000..fdde130286 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactoryPortCustomizer.java @@ -0,0 +1,30 @@ +package com.baeldung.spring.serverconfig; + +import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.stereotype.Component; +import reactor.netty.http.server.HttpServer; + +@Component +public class NettyWebServerFactoryPortCustomizer implements WebServerFactoryCustomizer { + + @Override + public void customize(NettyReactiveWebServerFactory serverFactory) { + serverFactory.addServerCustomizers(new PortCustomizer(8443)); + } + + private static class PortCustomizer implements NettyServerCustomizer { + + private final int port; + + private PortCustomizer(int port) { + this.port = port; + } + + @Override + public HttpServer apply(HttpServer httpServer) { + return httpServer.port(port); + } + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java new file mode 100644 index 0000000000..cf4e5ac8ea --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/NettyWebServerFactorySslCustomizer.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.serverconfig; + +import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; +import org.springframework.boot.web.embedded.netty.SslServerCustomizer; +import org.springframework.boot.web.server.Http2; +import org.springframework.boot.web.server.Ssl; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.stereotype.Component; + +@Component +public class NettyWebServerFactorySslCustomizer implements WebServerFactoryCustomizer { + + @Override + public void customize(NettyReactiveWebServerFactory serverFactory) { + Ssl ssl = new Ssl(); + ssl.setEnabled(true); + ssl.setKeyStore("classpath:sample.jks"); + ssl.setKeyAlias("alias"); + ssl.setKeyPassword("password"); + ssl.setKeyStorePassword("secret"); + Http2 http2 = new Http2(); + http2.setEnabled(false); + serverFactory.addServerCustomizers(new SslServerCustomizer(ssl, http2, null)); + serverFactory.setPort(8443); + } +} diff --git a/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/ServerConfigApplication.java b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/ServerConfigApplication.java new file mode 100644 index 0000000000..b4f6006be3 --- /dev/null +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/serverconfig/ServerConfigApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.serverconfig; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ServerConfigApplication { + + public static void main(String[] args) { + SpringApplication.run(ServerConfigApplication.class, args); + } +} diff --git a/spring-5-webflux/src/main/resources/logback.xml b/spring-5-webflux/src/main/resources/logback.xml new file mode 100644 index 0000000000..48b68c6bf1 --- /dev/null +++ b/spring-5-webflux/src/main/resources/logback.xml @@ -0,0 +1,31 @@ + + + + + + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable + + + + + + netty-access.log + + %msg%n + + + + + + + + + + + + + + + + diff --git a/spring-5-webflux/src/main/resources/sample.jks b/spring-5-webflux/src/main/resources/sample.jks new file mode 100644 index 0000000000000000000000000000000000000000..6aa9a28053a591e41453e665e5024e8a8cb78b3d GIT binary patch literal 2264 zcmchYX*3iJ7sqE|hQS!q5Mv)4GM2$i#uAFqC`%7x7baWA*i&dRX>3`uq(XS?3XSYp z%38`&ib7E$8j~$cF^}gt?|I+noW8#w?uYxk=iGD8|K9Vzd#pVc0002(2k@T|2@MMI zqxqr2AhQO*TVi`j@((S;e;g;l$#dAA{>vf0kX$R(Qn4oKgGEYjZ5zti2dw?Z6A zh%LuFCNI?9o+Z1duJL-++e#cjO`zlK?u9s030=k_*wD1#-$FbIDRDnA^vo@fm( zzjt(3VJrGOr0iHXSTM|rYN#>RZ@Dp`PwB2zrDQffLvuoR2~V3ReYa0&vU^dXd8isV zsAf*@!8s%xBvHLseXn6f?1kefe(8uAmAbaF$x{Ykzb6c6jdUwY1$y4tFzsj7 zIghr!T#ODfu@Po!a29@kXQ8kY#(LE<0o7?7PQ|eMeY@Equ?R-6*f@Na3o&stDQ=6( zQzDSQhCnS(9Bu9W_~giknP0vECqUsr4_9y_}nEU`cy z4}dApnAip92wMwgzciAFpc3i}+-#Zlq+iF7d1y}d4Qsp8=%l1N8NIs161I`HmkcpQ zY4*CUCFJJf(2!M{`&qQ}3($KeTQ=)mMrBs`DOb;%Of0tC)9he_p~w&CO#DfCgx(%s z{@|D(brX_Gb}ZDLmGej*JgEl0Et>q~kgTXuJg-PwvRjNx8sBbIShxD=xOySzw{;^X zAvrh5HTg>Xq@<{#^!Kg}B?qz@b<{ebD)yaSf&RChBIJQo-?Ahzw@qopSe^e&>^IuU zydM4Y1_C&>k7u|}=; z63R7$H6zat=hNExxEwXu1fQ*ytuEkP!{w{|#6TIEq1#*ck=6_NM*ILF65tmD-O5&R zMI!-MT<3U~t@}(CN4@RlZ~1I>C=!ywF)dNI{VvH;5Y3(Z4jY^%_c&fsm4Q`<1g|qX z&!h29jXjVE3nJnet*L)XL?-8<>qDbVGP%i^NwOZfwWO7?Mr!X7 zl}sG@9S_5}}td}$xrWIYY=e(VVBiv%A+M-{M z!3_^Tc=pV?niT!{D`!{e@W;MvrZ(OER{x7itVAtwE~spPtPtma|J=5dv&_oE!5H#` zdgXJ;+gJ4hI}*9QX9jpL`Gb)yCe%1}t!&O-^sihyZys%%5uF~WhsR_w(q7;vV5d4P zr%ZUA2}kO+L^2ePTgGT9Ua71w<+)poSyjTdLq&xbUn`<6&SpwFp(HRHUyU6J3WZ_! zfztko79+94Tq%mTYj53(RYcL&1~5`I#+w3`(Q|r+P(aT z%?r(^?IWw~19CB&uvXf(f7&BnEE{zwK4piVU`I4j1j?v5d4N<7VUJ8nM`$7S*mfKR z#9-JzPRZ?{M!@L+0N^V)IyeeP2T|^UK|m0QD+Ibs!wEoml^N!YO#vW~j~jraX(0A3 z6Kux?IRLez`O^X;{!4g%BhcRn>^H*qKZ3*|{_YGuz)KCJcu;)DSES5D2tDE`C02YR0R%Vy1T7k|RQ;3g<0icA$AuP0pOvc~jGl zz+NeKv_FT_;GWK&8XlDUv&hv9kxg?@c!bu?83i=YQ$S!K09Y)Glg3Hz?@|)ZCBlVz zP8i}#XZkMoje3I=h&I!!s_m?Qi@1MR`yv7X*yEs47qOs^t^?&=;*IQ!q&)gq_Sx5* z?fhU8Q*PSe*w7y)FH#P!9R^Xw!lTT+zI39L<&8cViaj$A(Z2Cg7!{V?uuyi#vlNCg z40i}2ivw&y&1-&Nh&WMG`&aIt>)(#tKTJ}^@696Kw1-{IzSOTnFF+0@k$o3%ZHS;Q#;t literal 0 HcmV?d00001 diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerTests.java b/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerLiveTest.java similarity index 97% rename from spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerTests.java rename to spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerLiveTest.java index 5112c8ceb2..4c6708e423 100644 --- a/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerTests.java +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/responsestatus/ResponseStatusControllerLiveTest.java @@ -9,7 +9,7 @@ import org.springframework.test.web.reactive.server.WebTestClient; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class ResponseStatusControllerTests { +public class ResponseStatusControllerLiveTest { @Autowired private WebTestClient testClient; diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingControllerIntegrationTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingControllerIntegrationTest.java new file mode 100644 index 0000000000..ce156beb3f --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingControllerIntegrationTest.java @@ -0,0 +1,41 @@ +package com.baeldung.spring.serverconfig; + +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; +import reactor.core.publisher.Mono; + +@RunWith(SpringRunner.class) +@WebFluxTest +public class GreetingControllerIntegrationTest { + + @Autowired + private WebTestClient webClient; + + @MockBean + private GreetingService greetingService; + + private final String name = "Baeldung"; + + @Before + public void setUp() { + when(greetingService.greet(name)).thenReturn(Mono.just("Greeting Baeldung")); + } + + @Test + public void shouldGreet() { + webClient.get().uri("/greet/{name}", name) + .exchange() + .expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo("Greeting Baeldung"); + } +} diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingLiveTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingLiveTest.java new file mode 100644 index 0000000000..2400272c6e --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingLiveTest.java @@ -0,0 +1,57 @@ +package com.baeldung.spring.serverconfig; + +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +import javax.net.ssl.SSLException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec; +import reactor.netty.http.client.HttpClient; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT) +@DirtiesContext +public class GreetingLiveTest { + + private static final String BASE_URL = "https://localhost:8443"; + + private WebTestClient webTestClient; + + @Before + public void setup() throws SSLException { + webTestClient = WebTestClient.bindToServer(getConnector()) + .baseUrl(BASE_URL) + .build(); + } + + @Test + public void shouldGreet() { + final String name = "Baeldung"; + + ResponseSpec response = webTestClient.get() + .uri("/greet/{name}", name) + .exchange(); + + response.expectStatus() + .isOk() + .expectBody(String.class) + .isEqualTo("Greeting Baeldung"); + } + + private ReactorClientHttpConnector getConnector() throws SSLException { + SslContext sslContext = SslContextBuilder + .forClient() + .trustManager(InsecureTrustManagerFactory.INSTANCE) + .build(); + HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext)); + return new ReactorClientHttpConnector(httpClient); + } +} diff --git a/spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingSkipAutoConfigLiveTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingSkipAutoConfigLiveTest.java new file mode 100644 index 0000000000..45918dfd70 --- /dev/null +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/serverconfig/GreetingSkipAutoConfigLiveTest.java @@ -0,0 +1,8 @@ +package com.baeldung.spring.serverconfig; + +import org.springframework.test.context.ActiveProfiles; + +@ActiveProfiles("skipAutoConfig") +public class GreetingSkipAutoConfigLiveTest extends GreetingLiveTest { + +} diff --git a/spring-5-webflux/src/test/resources/logback-test.xml b/spring-5-webflux/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..12cedf5952 --- /dev/null +++ b/spring-5-webflux/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + + + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable + + + + + + + From c2db7e83575dd8a4196979451f8e1f731bbd0f2f Mon Sep 17 00:00:00 2001 From: isaolmez Date: Wed, 27 Mar 2019 21:38:08 +0300 Subject: [PATCH 463/496] BAEL-2715: Removed spring-5-reactive-netty module --- pom.xml | 2 +- spring-5-reactive-netty/.gitignore | 11 ---- spring-5-reactive-netty/README.md | 3 - spring-5-reactive-netty/pom.xml | 51 ---------------- .../CustomNettyWebServerFactory.java | 36 ----------- .../serverconfig/GreetingController.java | 23 ------- .../serverconfig/GreetingService.java | 12 ---- .../NettyWebServerFactoryPortCustomizer.java | 30 ---------- .../NettyWebServerFactorySslCustomizer.java | 26 -------- .../serverconfig/ServerConfigApplication.java | 12 ---- .../src/main/resources/logback.xml | 31 ---------- .../src/main/resources/sample.jks | Bin 2264 -> 0 bytes .../GreetingControllerIntegrationTest.java | 41 ------------- .../serverconfig/GreetingLiveTest.java | 56 ------------------ .../GreetingSkipAutoConfigLiveTest.java | 8 --- .../src/test/resources/logback-test.xml | 13 ---- 16 files changed, 1 insertion(+), 354 deletions(-) delete mode 100644 spring-5-reactive-netty/.gitignore delete mode 100644 spring-5-reactive-netty/README.md delete mode 100644 spring-5-reactive-netty/pom.xml delete mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java delete mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingController.java delete mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingService.java delete mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactoryPortCustomizer.java delete mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactorySslCustomizer.java delete mode 100644 spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java delete mode 100644 spring-5-reactive-netty/src/main/resources/logback.xml delete mode 100644 spring-5-reactive-netty/src/main/resources/sample.jks delete mode 100644 spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingControllerIntegrationTest.java delete mode 100644 spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingLiveTest.java delete mode 100644 spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingSkipAutoConfigLiveTest.java delete mode 100644 spring-5-reactive-netty/src/test/resources/logback-test.xml diff --git a/pom.xml b/pom.xml index 7af92fbd11..7cb57a9077 100644 --- a/pom.xml +++ b/pom.xml @@ -577,12 +577,12 @@ spring-4 spring-5 + spring-5-webflux spring-5-mvc spring-5-reactive spring-5-reactive-client spring-5-reactive-oauth spring-5-reactive-security - spring-5-reactive-netty spring-5-security spring-5-security-oauth diff --git a/spring-5-reactive-netty/.gitignore b/spring-5-reactive-netty/.gitignore deleted file mode 100644 index 70ed41e73a..0000000000 --- a/spring-5-reactive-netty/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -# Folders # -**/.idea -**/target - -# Files # -*.log - -# Packaged files # -*.jar -*.war -*.ear \ No newline at end of file diff --git a/spring-5-reactive-netty/README.md b/spring-5-reactive-netty/README.md deleted file mode 100644 index 09f7cc0e24..0000000000 --- a/spring-5-reactive-netty/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Spring 5 Reactive Project With Netty Server - -Includes configuration options for Netty server. diff --git a/spring-5-reactive-netty/pom.xml b/spring-5-reactive-netty/pom.xml deleted file mode 100644 index 48fc0b201f..0000000000 --- a/spring-5-reactive-netty/pom.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - 4.0.0 - com.baeldung - spring-5-reactive-netty - 0.0.1-SNAPSHOT - spring-5-reactive-netty - jar - Spring 5 sample project about reactive web with Netty server - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../parent-boot-2 - - - - - org.springframework.boot - spring-boot-starter-webflux - - - - org.projectlombok - lombok - - - - org.springframework.boot - spring-boot-devtools - runtime - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java deleted file mode 100644 index 8a1cdbba97..0000000000 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/CustomNettyWebServerFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.serverconfig; - -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import reactor.netty.http.server.HttpServer; - -@Configuration -@Profile("skipAutoConfig") -public class CustomNettyWebServerFactory { - - @Bean - public NettyReactiveWebServerFactory nettyReactiveWebServerFactory() { - NettyReactiveWebServerFactory webServerFactory = new NettyReactiveWebServerFactory(); - webServerFactory.addServerCustomizers(new EventLoopNettyCustomizer()); - return webServerFactory; - } - - private static class EventLoopNettyCustomizer implements NettyServerCustomizer { - - @Override - public HttpServer apply(HttpServer httpServer) { - EventLoopGroup parentGroup = new NioEventLoopGroup(); - EventLoopGroup childGroup = new NioEventLoopGroup(); - return httpServer - .tcpConfiguration(tcpServer -> tcpServer.bootstrap( - serverBootstrap -> serverBootstrap.group(parentGroup, childGroup).channel(NioServerSocketChannel.class) - )); - } - } -} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingController.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingController.java deleted file mode 100644 index 9cb5b27ac5..0000000000 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingController.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.serverconfig; - -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 reactor.core.publisher.Mono; - -@RestController -@RequestMapping("/greet") -public class GreetingController { - - private final GreetingService greetingService; - - public GreetingController(GreetingService greetingService) { - this.greetingService = greetingService; - } - - @GetMapping("/{name}") - private Mono greet(@PathVariable String name) { - return greetingService.greet(name); - } -} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingService.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingService.java deleted file mode 100644 index 5440f526aa..0000000000 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/GreetingService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.serverconfig; - -import org.springframework.stereotype.Service; -import reactor.core.publisher.Mono; - -@Service -public class GreetingService { - - public Mono greet(String name) { - return Mono.just("Greeting " + name); - } -} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactoryPortCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactoryPortCustomizer.java deleted file mode 100644 index 152e1285aa..0000000000 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactoryPortCustomizer.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.serverconfig; - -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.netty.NettyServerCustomizer; -import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.stereotype.Component; -import reactor.netty.http.server.HttpServer; - -@Component -public class NettyWebServerFactoryPortCustomizer implements WebServerFactoryCustomizer { - - @Override - public void customize(NettyReactiveWebServerFactory serverFactory) { - serverFactory.addServerCustomizers(new PortCustomizer(8443)); - } - - private static class PortCustomizer implements NettyServerCustomizer { - - private final int port; - - private PortCustomizer(int port) { - this.port = port; - } - - @Override - public HttpServer apply(HttpServer httpServer) { - return httpServer.port(port); - } - } -} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactorySslCustomizer.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactorySslCustomizer.java deleted file mode 100644 index d0ad0dcac5..0000000000 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/NettyWebServerFactorySslCustomizer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.serverconfig; - -import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; -import org.springframework.boot.web.embedded.netty.SslServerCustomizer; -import org.springframework.boot.web.server.Http2; -import org.springframework.boot.web.server.Ssl; -import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.stereotype.Component; - -@Component -public class NettyWebServerFactorySslCustomizer implements WebServerFactoryCustomizer { - - @Override - public void customize(NettyReactiveWebServerFactory serverFactory) { - Ssl ssl = new Ssl(); - ssl.setEnabled(true); - ssl.setKeyStore("classpath:sample.jks"); - ssl.setKeyAlias("alias"); - ssl.setKeyPassword("password"); - ssl.setKeyStorePassword("secret"); - Http2 http2 = new Http2(); - http2.setEnabled(false); - serverFactory.addServerCustomizers(new SslServerCustomizer(ssl, http2, null)); - serverFactory.setPort(8443); - } -} diff --git a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java b/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java deleted file mode 100644 index 9d420cc7da..0000000000 --- a/spring-5-reactive-netty/src/main/java/com/baeldung/serverconfig/ServerConfigApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.serverconfig; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class ServerConfigApplication { - - public static void main(String[] args) { - SpringApplication.run(ServerConfigApplication.class, args); - } -} diff --git a/spring-5-reactive-netty/src/main/resources/logback.xml b/spring-5-reactive-netty/src/main/resources/logback.xml deleted file mode 100644 index 48b68c6bf1..0000000000 --- a/spring-5-reactive-netty/src/main/resources/logback.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - - - - - netty-access.log - - %msg%n - - - - - - - - - - - - - - - - diff --git a/spring-5-reactive-netty/src/main/resources/sample.jks b/spring-5-reactive-netty/src/main/resources/sample.jks deleted file mode 100644 index 6aa9a28053a591e41453e665e5024e8a8cb78b3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2264 zcmchYX*3iJ7sqE|hQS!q5Mv)4GM2$i#uAFqC`%7x7baWA*i&dRX>3`uq(XS?3XSYp z%38`&ib7E$8j~$cF^}gt?|I+noW8#w?uYxk=iGD8|K9Vzd#pVc0002(2k@T|2@MMI zqxqr2AhQO*TVi`j@((S;e;g;l$#dAA{>vf0kX$R(Qn4oKgGEYjZ5zti2dw?Z6A zh%LuFCNI?9o+Z1duJL-++e#cjO`zlK?u9s030=k_*wD1#-$FbIDRDnA^vo@fm( zzjt(3VJrGOr0iHXSTM|rYN#>RZ@Dp`PwB2zrDQffLvuoR2~V3ReYa0&vU^dXd8isV zsAf*@!8s%xBvHLseXn6f?1kefe(8uAmAbaF$x{Ykzb6c6jdUwY1$y4tFzsj7 zIghr!T#ODfu@Po!a29@kXQ8kY#(LE<0o7?7PQ|eMeY@Equ?R-6*f@Na3o&stDQ=6( zQzDSQhCnS(9Bu9W_~giknP0vECqUsr4_9y_}nEU`cy z4}dApnAip92wMwgzciAFpc3i}+-#Zlq+iF7d1y}d4Qsp8=%l1N8NIs161I`HmkcpQ zY4*CUCFJJf(2!M{`&qQ}3($KeTQ=)mMrBs`DOb;%Of0tC)9he_p~w&CO#DfCgx(%s z{@|D(brX_Gb}ZDLmGej*JgEl0Et>q~kgTXuJg-PwvRjNx8sBbIShxD=xOySzw{;^X zAvrh5HTg>Xq@<{#^!Kg}B?qz@b<{ebD)yaSf&RChBIJQo-?Ahzw@qopSe^e&>^IuU zydM4Y1_C&>k7u|}=; z63R7$H6zat=hNExxEwXu1fQ*ytuEkP!{w{|#6TIEq1#*ck=6_NM*ILF65tmD-O5&R zMI!-MT<3U~t@}(CN4@RlZ~1I>C=!ywF)dNI{VvH;5Y3(Z4jY^%_c&fsm4Q`<1g|qX z&!h29jXjVE3nJnet*L)XL?-8<>qDbVGP%i^NwOZfwWO7?Mr!X7 zl}sG@9S_5}}td}$xrWIYY=e(VVBiv%A+M-{M z!3_^Tc=pV?niT!{D`!{e@W;MvrZ(OER{x7itVAtwE~spPtPtma|J=5dv&_oE!5H#` zdgXJ;+gJ4hI}*9QX9jpL`Gb)yCe%1}t!&O-^sihyZys%%5uF~WhsR_w(q7;vV5d4P zr%ZUA2}kO+L^2ePTgGT9Ua71w<+)poSyjTdLq&xbUn`<6&SpwFp(HRHUyU6J3WZ_! zfztko79+94Tq%mTYj53(RYcL&1~5`I#+w3`(Q|r+P(aT z%?r(^?IWw~19CB&uvXf(f7&BnEE{zwK4piVU`I4j1j?v5d4N<7VUJ8nM`$7S*mfKR z#9-JzPRZ?{M!@L+0N^V)IyeeP2T|^UK|m0QD+Ibs!wEoml^N!YO#vW~j~jraX(0A3 z6Kux?IRLez`O^X;{!4g%BhcRn>^H*qKZ3*|{_YGuz)KCJcu;)DSES5D2tDE`C02YR0R%Vy1T7k|RQ;3g<0icA$AuP0pOvc~jGl zz+NeKv_FT_;GWK&8XlDUv&hv9kxg?@c!bu?83i=YQ$S!K09Y)Glg3Hz?@|)ZCBlVz zP8i}#XZkMoje3I=h&I!!s_m?Qi@1MR`yv7X*yEs47qOs^t^?&=;*IQ!q&)gq_Sx5* z?fhU8Q*PSe*w7y)FH#P!9R^Xw!lTT+zI39L<&8cViaj$A(Z2Cg7!{V?uuyi#vlNCg z40i}2ivw&y&1-&Nh&WMG`&aIt>)(#tKTJ}^@696Kw1-{IzSOTnFF+0@k$o3%ZHS;Q#;t diff --git a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingControllerIntegrationTest.java b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingControllerIntegrationTest.java deleted file mode 100644 index 3c2c08321a..0000000000 --- a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingControllerIntegrationTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.serverconfig; - -import static org.mockito.Mockito.when; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; -import reactor.core.publisher.Mono; - -@RunWith(SpringRunner.class) -@WebFluxTest -public class GreetingControllerIntegrationTest { - - @Autowired - private WebTestClient webClient; - - @MockBean - private GreetingService greetingService; - - private final String name = "Baeldung"; - - @Before - public void setUp() { - when(greetingService.greet(name)).thenReturn(Mono.just("Greeting Baeldung")); - } - - @Test - public void shouldGreet() { - webClient.get().uri("/greet/{name}", name) - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .isEqualTo("Greeting Baeldung"); - } -} diff --git a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingLiveTest.java b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingLiveTest.java deleted file mode 100644 index 7c4a37c890..0000000000 --- a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingLiveTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.baeldung.serverconfig; - -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import javax.net.ssl.SSLException; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec; -import reactor.netty.http.client.HttpClient; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT) -public class GreetingLiveTest { - - private static final String BASE_URL = "https://localhost:8443"; - - private WebTestClient webTestClient; - - @Before - public void setup() throws SSLException { - webTestClient = WebTestClient.bindToServer(getConnector()) - .baseUrl(BASE_URL) - .build(); - } - - @Test - public void shouldGreet() { - final String name = "Baeldung"; - - ResponseSpec response = webTestClient.get() - .uri("/greet/{name}", name) - .exchange(); - - response.expectStatus() - .isOk() - .expectBody(String.class) - .isEqualTo("Greeting Baeldung"); - } - - private ReactorClientHttpConnector getConnector() throws SSLException { - SslContext sslContext = SslContextBuilder - .forClient() - .trustManager(InsecureTrustManagerFactory.INSTANCE) - .build(); - HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(sslContext)); - return new ReactorClientHttpConnector(httpClient); - } -} diff --git a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingSkipAutoConfigLiveTest.java b/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingSkipAutoConfigLiveTest.java deleted file mode 100644 index 646742b3d7..0000000000 --- a/spring-5-reactive-netty/src/test/java/com/baeldung/serverconfig/GreetingSkipAutoConfigLiveTest.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.serverconfig; - -import org.springframework.test.context.ActiveProfiles; - -@ActiveProfiles("skipAutoConfig") -public class GreetingSkipAutoConfigLiveTest extends GreetingLiveTest { - -} diff --git a/spring-5-reactive-netty/src/test/resources/logback-test.xml b/spring-5-reactive-netty/src/test/resources/logback-test.xml deleted file mode 100644 index 12cedf5952..0000000000 --- a/spring-5-reactive-netty/src/test/resources/logback-test.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1.}): %msg%n%throwable - - - - - - - From 73a58cc3b1f450df6fb8a263d9e38794d0b03dde Mon Sep 17 00:00:00 2001 From: isaolmez Date: Wed, 27 Mar 2019 21:41:07 +0300 Subject: [PATCH 464/496] BAEL-2715: Removed spring-5-reactive-netty module --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7cb57a9077..615fc7b46e 100644 --- a/pom.xml +++ b/pom.xml @@ -577,7 +577,7 @@ spring-4 spring-5 - spring-5-webflux + spring-5-webflux spring-5-mvc spring-5-reactive spring-5-reactive-client From cf37a11ddfa0c87bd4dcae56aee62b48d900a11c Mon Sep 17 00:00:00 2001 From: isaolmez Date: Wed, 27 Mar 2019 21:46:44 +0300 Subject: [PATCH 465/496] BAEL-2715: Removed spring-5-reactive-netty module --- spring-5-webflux/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 spring-5-webflux/.gitignore diff --git a/spring-5-webflux/.gitignore b/spring-5-webflux/.gitignore new file mode 100644 index 0000000000..aa4871eeea --- /dev/null +++ b/spring-5-webflux/.gitignore @@ -0,0 +1,2 @@ +# Files # +*.log \ No newline at end of file From b94dedadd55ec6b53a0cf7ca9369560d10c95138 Mon Sep 17 00:00:00 2001 From: Loredana Date: Wed, 27 Mar 2019 22:21:01 +0200 Subject: [PATCH 466/496] move code to mongodb module --- .../mongodb/ManualEmbeddedMongoDbIntegrationTest.java | 0 .../mongodb/MongoDbSpringIntegrationTest.java | 0 spring-boot/pom.xml | 11 +---------- 3 files changed, 1 insertion(+), 10 deletions(-) rename {spring-boot => persistence-modules/spring-boot-persistence-mongodb}/src/test/java/com/baeldung/mongodb/ManualEmbeddedMongoDbIntegrationTest.java (100%) rename {spring-boot => persistence-modules/spring-boot-persistence-mongodb}/src/test/java/com/baeldung/mongodb/MongoDbSpringIntegrationTest.java (100%) diff --git a/spring-boot/src/test/java/com/baeldung/mongodb/ManualEmbeddedMongoDbIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/ManualEmbeddedMongoDbIntegrationTest.java similarity index 100% rename from spring-boot/src/test/java/com/baeldung/mongodb/ManualEmbeddedMongoDbIntegrationTest.java rename to persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/ManualEmbeddedMongoDbIntegrationTest.java diff --git a/spring-boot/src/test/java/com/baeldung/mongodb/MongoDbSpringIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbSpringIntegrationTest.java similarity index 100% rename from spring-boot/src/test/java/com/baeldung/mongodb/MongoDbSpringIntegrationTest.java rename to persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbSpringIntegrationTest.java diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml index 2e463e0189..ed2d8259df 100644 --- a/spring-boot/pom.xml +++ b/spring-boot/pom.xml @@ -15,16 +15,7 @@ - - - org.springframework.boot - spring-boot-starter-data-mongodb - - - de.flapdoodle.embed - de.flapdoodle.embed.mongo - test - + org.junit.jupiter From a22ce57c66b4e4f026d3634ad1d17420b0d44233 Mon Sep 17 00:00:00 2001 From: TINO Date: Wed, 27 Mar 2019 23:24:56 +0300 Subject: [PATCH 467/496] BAEL - 2829 Review comments incorporated --- .../{PersonRepository.java => EmployeeRepository.java} | 0 ...ntegrationTest.java => EmployeeRepositoryIntegrationTest.java} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/{PersonRepository.java => EmployeeRepository.java} (100%) rename persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/{PersonRepositoryIntegrationTest.java => EmployeeRepositoryIntegrationTest.java} (100%) diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/EmployeeRepository.java similarity index 100% rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/PersonRepository.java rename to persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/EmployeeRepository.java diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/EmployeeRepositoryIntegrationTest.java similarity index 100% rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/PersonRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/EmployeeRepositoryIntegrationTest.java From 78db505e7b0209985a7200d27e36f774cf958b2d Mon Sep 17 00:00:00 2001 From: Loredana Date: Wed, 27 Mar 2019 22:25:46 +0200 Subject: [PATCH 468/496] move code --- .../spring-boot-persistence-mongodb/pom.xml | 7 ++++++- .../com/baeldung/mongodb/MongoDbSpringIntegrationTest.java | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/persistence-modules/spring-boot-persistence-mongodb/pom.xml b/persistence-modules/spring-boot-persistence-mongodb/pom.xml index 86b93c7826..585e54bf57 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/pom.xml +++ b/persistence-modules/spring-boot-persistence-mongodb/pom.xml @@ -25,6 +25,11 @@ org.springframework.boot spring-boot-starter-data-mongodb + + de.flapdoodle.embed + de.flapdoodle.embed.mongo + test + org.junit.jupiter @@ -102,4 +107,4 @@ - \ No newline at end of file + diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbSpringIntegrationTest.java b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbSpringIntegrationTest.java index 39127f62e9..954bae3684 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbSpringIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/mongodb/MongoDbSpringIntegrationTest.java @@ -2,7 +2,6 @@ package com.baeldung.mongodb; import static org.assertj.core.api.Assertions.assertThat; -import org.baeldung.boot.Application; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -12,10 +11,11 @@ import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import com.baeldung.SpringBootPersistenceApplication; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.DBObject; -@ContextConfiguration(classes = Application.class) +@ContextConfiguration(classes = SpringBootPersistenceApplication.class) @DataMongoTest @ExtendWith(SpringExtension.class) public class MongoDbSpringIntegrationTest { From 90eb4ba3599a8182bd4854ca085a911197048d8a Mon Sep 17 00:00:00 2001 From: TINO Date: Wed, 27 Mar 2019 23:29:15 +0300 Subject: [PATCH 469/496] BAEL 2829 --- .../java/com/baeldung/domain/Employee.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Employee.java diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Employee.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Employee.java new file mode 100644 index 0000000000..f2363cf746 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/domain/Employee.java @@ -0,0 +1,36 @@ +package com.baeldung.domain; + +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class Employee { + + @Id + private Long id; + private String name; + + public Employee() { + } + + public Employee(Long id, String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} From bce367c5f2d3be779cace43847dd4cccd781ad21 Mon Sep 17 00:00:00 2001 From: Loredana Date: Wed, 27 Mar 2019 22:41:19 +0200 Subject: [PATCH 470/496] update readme --- persistence-modules/spring-boot-persistence-mongodb/README.md | 1 + spring-boot/README.MD | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-modules/spring-boot-persistence-mongodb/README.md b/persistence-modules/spring-boot-persistence-mongodb/README.md index f093d4baf0..40f9f40749 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/README.md +++ b/persistence-modules/spring-boot-persistence-mongodb/README.md @@ -1,3 +1,4 @@ # Relevant Articles - [Auto-Generated Field for MongoDB using Spring Boot](https://www.baeldung.com/spring-boot-mongodb-auto-generated-field) +- [Spring Boot Integration Testing with Embedded MongoDB](http://www.baeldung.com/spring-boot-embedded-mongodb) diff --git a/spring-boot/README.MD b/spring-boot/README.MD index b5f0bf39b6..7d270c9c25 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -28,7 +28,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Boot Exit Codes](http://www.baeldung.com/spring-boot-exit-codes) - [Guide to the Favicon in Spring Boot](http://www.baeldung.com/spring-boot-favicon) - [Spring Shutdown Callbacks](http://www.baeldung.com/spring-shutdown-callbacks) -- [Spring Boot Integration Testing with Embedded MongoDB](http://www.baeldung.com/spring-boot-embedded-mongodb) - [Container Configuration in Spring Boot 2](http://www.baeldung.com/embeddedservletcontainercustomizer-configurableembeddedservletcontainer-spring-boot) - [Introduction to Chaos Monkey](https://www.baeldung.com/spring-boot-chaos-monkey) - [Spring Component Scanning](https://www.baeldung.com/spring-component-scanning) From 76ff0d25cfd9d5aabc312770eaf4d64bf3213431 Mon Sep 17 00:00:00 2001 From: Blockchain-Trainer <46881425+blockchain-trainer@users.noreply.github.com> Date: Thu, 28 Mar 2019 16:03:40 +0530 Subject: [PATCH 471/496] [BAEL-2718] - Spring JPA Batch Inserts (#6333) * [BAEL-2718] - Spring JPA Batch Inserts * [BAEL-2718] - Spring JPA Batch Inserts (New PR) * [BAEL-2718] - Spring JPA Batch Inserts New PR * [BAEL-2718] - Spring JPA Batch Inserts * BAEL-2718 - formatting (tab to space) --- persistence-modules/spring-data-jpa/pom.xml | 9 +++ .../batchinserts/CustomerController.java | 43 ++++++++++++++ .../baeldung/batchinserts/model/Customer.java | 56 +++++++++++++++++++ .../repository/CustomerRepository.java | 15 +++++ .../src/main/resources/application.properties | 7 ++- .../BatchInsertIntegrationTest.java | 44 +++++++++++++++ 6 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/CustomerController.java create mode 100644 persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/model/Customer.java create mode 100644 persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/repository/CustomerRepository.java create mode 100644 persistence-modules/spring-data-jpa/src/test/java/com/baeldung/batchinserts/BatchInsertIntegrationTest.java diff --git a/persistence-modules/spring-data-jpa/pom.xml b/persistence-modules/spring-data-jpa/pom.xml index 401f4877ac..c512994931 100644 --- a/persistence-modules/spring-data-jpa/pom.xml +++ b/persistence-modules/spring-data-jpa/pom.xml @@ -53,6 +53,15 @@ spring-security-test test + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + com.google.guava diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/CustomerController.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/CustomerController.java new file mode 100644 index 0000000000..7623d4d166 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/CustomerController.java @@ -0,0 +1,43 @@ +package com.baeldung.batchinserts; + +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.batchinserts.model.Customer; +import com.baeldung.batchinserts.repository.CustomerRepository; + +/** + * A simple controller to test the JPA CrudRepository operations + * controllers + * + * @author ysharma2512 + * + */ +@RestController +public class CustomerController { + + @Autowired + CustomerRepository customerRepository; + + public CustomerController(CustomerRepository customerRepository2) { + this.customerRepository = customerRepository2; + } + + @PostMapping("/customers") + public ResponseEntity> insertCustomers() throws URISyntaxException { + Customer c1 = new Customer("James", "Gosling"); + Customer c2 = new Customer("Doug", "Lea"); + Customer c3 = new Customer("Martin", "Fowler"); + Customer c4 = new Customer("Brian", "Goetz"); + List customers = Arrays.asList(c1, c2, c3, c4); + customerRepository.saveAll(customers); + return ResponseEntity.ok(customers); + } + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/model/Customer.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/model/Customer.java new file mode 100644 index 0000000000..4d82cf12a2 --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/model/Customer.java @@ -0,0 +1,56 @@ +package com.baeldung.batchinserts.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +/** + * Customer Entity class + * @author ysharma2512 + * + */ +@Entity +public class Customer { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + private String firstName; + private String lastName; + + public Customer(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public String toString() { + return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName); + } + +} diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/repository/CustomerRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/repository/CustomerRepository.java new file mode 100644 index 0000000000..ab0214bade --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/batchinserts/repository/CustomerRepository.java @@ -0,0 +1,15 @@ +package com.baeldung.batchinserts.repository; + +import org.springframework.data.repository.CrudRepository; + +import com.baeldung.batchinserts.model.Customer; + +/** + * JPA CrudRepository interface + * + * @author ysharma2512 + * + */ +public interface CustomerRepository extends CrudRepository{ + +} diff --git a/persistence-modules/spring-data-jpa/src/main/resources/application.properties b/persistence-modules/spring-data-jpa/src/main/resources/application.properties index 37fb9ca9c4..239f81db7b 100644 --- a/persistence-modules/spring-data-jpa/src/main/resources/application.properties +++ b/persistence-modules/spring-data-jpa/src/main/resources/application.properties @@ -14,4 +14,9 @@ hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFa spring.datasource.data=import_entities.sql -spring.main.allow-bean-definition-overriding=true \ No newline at end of file +spring.main.allow-bean-definition-overriding=true + +spring.jpa.properties.hibernate.jdbc.batch_size=4 +spring.jpa.properties.hibernate.order_inserts=true +spring.jpa.properties.hibernate.order_updates=true +spring.jpa.properties.hibernate.generate_statistics=true \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/batchinserts/BatchInsertIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/batchinserts/BatchInsertIntegrationTest.java new file mode 100644 index 0000000000..f60e0d21bf --- /dev/null +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/batchinserts/BatchInsertIntegrationTest.java @@ -0,0 +1,44 @@ +package com.baeldung.batchinserts; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import com.baeldung.batchinserts.CustomerController; +import com.baeldung.batchinserts.repository.CustomerRepository; +import com.baeldung.config.PersistenceConfiguration; +import com.baeldung.config.PersistenceProductConfiguration; +import com.baeldung.config.PersistenceUserConfiguration; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +@ContextConfiguration(classes = { PersistenceConfiguration.class, PersistenceProductConfiguration.class, PersistenceUserConfiguration.class }) +public class BatchInsertIntegrationTest { + + @Autowired + private CustomerRepository customerRepository; + private MockMvc mockMvc; + @Before + public void setUp() throws Exception { + mockMvc = MockMvcBuilders.standaloneSetup( new CustomerController(customerRepository)) + .build(); + } + + @Test + public void whenInsertingCustomers_thenCustomersAreCreated() throws Exception { + this.mockMvc.perform(post("/customers")) + .andExpect(status().isOk()); + } + +} \ No newline at end of file From bdd8fff37889802552ab7d219928ae8bcce89f60 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Thu, 28 Mar 2019 21:45:43 +0800 Subject: [PATCH 472/496] Update README.md --- tensorflow-java/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow-java/README.md b/tensorflow-java/README.md index aac5b7544c..aa9e9e56b9 100644 --- a/tensorflow-java/README.md +++ b/tensorflow-java/README.md @@ -1,3 +1,3 @@ ## Relevant articles: -- [TensorFlow for Java](https://www.baeldung.com/xxxx) +- [TensorFlow for Java](https://www.baeldung.com/tensorflow-java) From 580ed9f6262675163d674eb8d4d4824aee82fa87 Mon Sep 17 00:00:00 2001 From: Antonio Moreno Date: Thu, 28 Mar 2019 18:20:54 +0100 Subject: [PATCH 473/496] BAEL 2772 - Find If 2 Numbers Are Relatively Prime in Java (#6599) * Hexagonal Architecture - Eval Article * BAEL-2772 Relatively Prime code --- .../relativelyprime/RelativelyPrime.java | 45 ++++++++++++++++ .../RelativelyPrimeUnitTest.java | 51 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/relativelyprime/RelativelyPrime.java create mode 100644 algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/relativelyprime/RelativelyPrimeUnitTest.java diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/relativelyprime/RelativelyPrime.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/relativelyprime/RelativelyPrime.java new file mode 100644 index 0000000000..fbea87be30 --- /dev/null +++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/relativelyprime/RelativelyPrime.java @@ -0,0 +1,45 @@ +package com.baeldung.algorithms.relativelyprime; + +import java.math.BigInteger; + +class RelativelyPrime { + + static boolean iterativeRelativelyPrime(int a, int b) { + return iterativeGCD(a, b) == 1; + } + + static boolean recursiveRelativelyPrime(int a, int b) { + return recursiveGCD(a, b) == 1; + } + + static boolean bigIntegerRelativelyPrime(int a, int b) { + return BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).equals(BigInteger.ONE); + } + + private static int iterativeGCD(int a, int b) { + int tmp; + while (b != 0) { + if (a < b) { + tmp = a; + a = b; + b = tmp; + } + tmp = b; + b = a % b; + a = tmp; + } + return a; + } + + private static int recursiveGCD(int a, int b) { + if (b == 0) { + return a; + } + if (a < b) { + return recursiveGCD(b, a); + } + return recursiveGCD(b, a % b); + } + + +} diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/relativelyprime/RelativelyPrimeUnitTest.java b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/relativelyprime/RelativelyPrimeUnitTest.java new file mode 100644 index 0000000000..84bb2620af --- /dev/null +++ b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/relativelyprime/RelativelyPrimeUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.algorithms.relativelyprime; + +import org.junit.Test; + +import static com.baeldung.algorithms.relativelyprime.RelativelyPrime.*; +import static org.assertj.core.api.Assertions.assertThat; + +public class RelativelyPrimeUnitTest { + + @Test + public void givenNonRelativelyPrimeNumbers_whenCheckingIteratively_shouldReturnFalse() { + + boolean result = iterativeRelativelyPrime(45, 35); + assertThat(result).isFalse(); + } + + @Test + public void givenRelativelyPrimeNumbers_whenCheckingIteratively_shouldReturnTrue() { + + boolean result = iterativeRelativelyPrime(500, 501); + assertThat(result).isTrue(); + } + + @Test + public void givenNonRelativelyPrimeNumbers_whenCheckingRecursively_shouldReturnFalse() { + + boolean result = recursiveRelativelyPrime(45, 35); + assertThat(result).isFalse(); + } + + @Test + public void givenRelativelyPrimeNumbers_whenCheckingRecursively_shouldReturnTrue() { + + boolean result = recursiveRelativelyPrime(500, 501); + assertThat(result).isTrue(); + } + + @Test + public void givenNonRelativelyPrimeNumbers_whenCheckingUsingBigIntegers_shouldReturnFalse() { + + boolean result = bigIntegerRelativelyPrime(45, 35); + assertThat(result).isFalse(); + } + + @Test + public void givenRelativelyPrimeNumbers_whenCheckingBigIntegers_shouldReturnTrue() { + + boolean result = bigIntegerRelativelyPrime(500, 501); + assertThat(result).isTrue(); + } +} From 4195b7e40630c9f1d86439bc5a043d061e763924 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Fri, 29 Mar 2019 00:24:14 +0530 Subject: [PATCH 474/496] [BAEL-10897] - Fixed tomcat connection pool issue and CarRepositoryIntegrationTest --- persistence-modules/spring-boot-persistence/pom.xml | 6 ++++++ .../main/java/com/baeldung/{exists => boot/domain}/Car.java | 4 ++-- .../baeldung/{exists => boot/repository}/CarRepository.java | 4 +++- .../com/baeldung/exists/CarRepositoryIntegrationTest.java | 6 +++++- .../SpringBootTomcatConnectionPoolIntegrationTest.java | 2 +- 5 files changed, 17 insertions(+), 5 deletions(-) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{exists => boot/domain}/Car.java (93%) rename persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/{exists => boot/repository}/CarRepository.java (91%) diff --git a/persistence-modules/spring-boot-persistence/pom.xml b/persistence-modules/spring-boot-persistence/pom.xml index 72ac40222f..ca7c7306e7 100644 --- a/persistence-modules/spring-boot-persistence/pom.xml +++ b/persistence-modules/spring-boot-persistence/pom.xml @@ -25,6 +25,12 @@ org.springframework.boot spring-boot-starter-data-jpa + + + com.zaxxer + HikariCP + + org.springframework.boot diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/Car.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Car.java similarity index 93% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/Car.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Car.java index bf09caf6ff..736c12fb07 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/Car.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/domain/Car.java @@ -1,4 +1,4 @@ -package com.baeldung.exists; +package com.baeldung.boot.domain; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -17,7 +17,7 @@ public class Car { private Integer power; private String model; - Car() { + public Car() { } diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/CarRepository.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/CarRepository.java similarity index 91% rename from persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/CarRepository.java rename to persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/CarRepository.java index a54f19f4cd..0176b14169 100644 --- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/exists/CarRepository.java +++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/repository/CarRepository.java @@ -1,10 +1,12 @@ -package com.baeldung.exists; +package com.baeldung.boot.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import com.baeldung.boot.domain.Car; + /** * @author paullatzelsperger * @since 2019-03-20 diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java index 1633df35d6..f9a48a7e66 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java @@ -13,11 +13,15 @@ import org.springframework.data.domain.Example; import org.springframework.data.domain.ExampleMatcher; import org.springframework.test.context.junit4.SpringRunner; +import com.baeldung.boot.Application; +import com.baeldung.boot.domain.Car; +import com.baeldung.boot.repository.CarRepository; + import java.util.Arrays; import java.util.List; @RunWith(SpringRunner.class) -@SpringBootTest +@SpringBootTest(classes = {Application.class}) public class CarRepositoryIntegrationTest { @Autowired diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java index 76a4261a24..5400d76fbe 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java @@ -20,6 +20,6 @@ public class SpringBootTomcatConnectionPoolIntegrationTest { @Test public void givenTomcatConnectionPoolInstance_whenCheckedPoolClassName_thenCorrect() { - assertThat(dataSource.getClass().getName()).isEqualTo("com.zaxxer.hikari.HikariDataSource"); + assertThat(dataSource.getClass().getName()).isEqualTo("org.apache.tomcat.jdbc.pool.DataSource"); } } From 9687c88abf2d33b3e31b11b3587165d1a5a13451 Mon Sep 17 00:00:00 2001 From: dev-chirag <41482403+dev-chirag@users.noreply.github.com> Date: Fri, 29 Mar 2019 06:26:15 +0530 Subject: [PATCH 475/496] BAEL2489 - Avoid check for null statement in Java (#6411) * BAEL2489 - Avoid check for null statement in Java * BAEL2489 Avoid check for null statement in Java * BAEL2489 Avoid check for null statement in Java * BAEL2489 Avoid check for null statement in Java * BAEL2489 Avoid check for null statement in Java * BAEL2489 Avoid check for null statement in Java - Removing unused pom changes * BAEL2489 Avoid check for null statement in Java - Removing unused pom changes * Delete pom.xml Removing unused changes in core-java * BAEL2489 Avoid check for null statement in Java - Removing unused pom changes --- patterns/design-patterns-2/pom.xml | 18 ++++++++ .../java/com/baeldung/nulls/APIContracts.java | 30 +++++++++++++ .../java/com/baeldung/nulls/Assertions.java | 13 ++++++ .../com/baeldung/nulls/EmptyCollections.java | 25 +++++++++++ .../baeldung/nulls/FindBugsAnnotations.java | 30 +++++++++++++ .../com/baeldung/nulls/Preconditions.java | 39 +++++++++++++++++ .../baeldung/nulls/PrimitivesAndWrapper.java | 21 ++++++++++ .../java/com/baeldung/nulls/UsingLombok.java | 10 +++++ .../java/com/baeldung/nulls/UsingObjects.java | 11 +++++ .../com/baeldung/nulls/UsingOptional.java | 27 ++++++++++++ .../com/baeldung/nulls/UsingStringUtils.java | 22 ++++++++++ .../nulls/PrimitivesAndWrapperUnitTest.java | 35 ++++++++++++++++ .../baeldung/nulls/UsingLombokUnitTest.java | 24 +++++++++++ .../baeldung/nulls/UsingObjectsUnitTest.java | 30 +++++++++++++ .../baeldung/nulls/UsingOptionalUnitTest.java | 42 +++++++++++++++++++ .../nulls/UsingStringUtilsUnitTest.java | 42 +++++++++++++++++++ 16 files changed, 419 insertions(+) create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/APIContracts.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/Assertions.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/EmptyCollections.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/FindBugsAnnotations.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/Preconditions.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/PrimitivesAndWrapper.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingLombok.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingObjects.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingOptional.java create mode 100644 patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingStringUtils.java create mode 100644 patterns/design-patterns-2/src/test/java/com/baeldung/nulls/PrimitivesAndWrapperUnitTest.java create mode 100644 patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingLombokUnitTest.java create mode 100644 patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingObjectsUnitTest.java create mode 100644 patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingOptionalUnitTest.java create mode 100644 patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingStringUtilsUnitTest.java diff --git a/patterns/design-patterns-2/pom.xml b/patterns/design-patterns-2/pom.xml index 2a0213065b..5c3e70b046 100644 --- a/patterns/design-patterns-2/pom.xml +++ b/patterns/design-patterns-2/pom.xml @@ -15,11 +15,29 @@ + + org.jetbrains + annotations + ${intellij.annotations.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + UTF-8 1.8 1.8 + 16.0.2 + 3.5 diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/APIContracts.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/APIContracts.java new file mode 100644 index 0000000000..7d6abf53b8 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/APIContracts.java @@ -0,0 +1,30 @@ +package com.baeldung.nulls; + +public class APIContracts { + + /** + * Prints the value of {@code param} if not null. Prints {@code null} otherwise. + * + * @param param + */ + public void print(Object param) { + System.out.println("Printing " + param); + } + + /** + * @return non null result + * @throws Exception - if result is null + */ + public Object process() throws Exception { + Object result = doSomething(); + if (result == null) { + throw new Exception("Processing fail. Got a null response"); + } else { + return result; + } + } + + private Object doSomething() { + return null; + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/Assertions.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/Assertions.java new file mode 100644 index 0000000000..a0d692623f --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/Assertions.java @@ -0,0 +1,13 @@ +package com.baeldung.nulls; + +public class Assertions { + + public void accept(Object param){ + assert param != null; + + doSomething(param); + } + + private void doSomething(Object param) { + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/EmptyCollections.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/EmptyCollections.java new file mode 100644 index 0000000000..5958cf8dc6 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/EmptyCollections.java @@ -0,0 +1,25 @@ +package com.baeldung.nulls; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class EmptyCollections { + + public List names() { + if (userExist()) { + return Stream.of(readName()).collect(Collectors.toList()); + } else { + return Collections.emptyList(); + } + } + + private boolean userExist() { + return false; + } + + private String readName() { + return "test"; + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/FindBugsAnnotations.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/FindBugsAnnotations.java new file mode 100644 index 0000000000..697d5e4959 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/FindBugsAnnotations.java @@ -0,0 +1,30 @@ +package com.baeldung.nulls; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + + +public class FindBugsAnnotations { + + public void accept(@NotNull Object param) { + System.out.println(param.toString()); + } + + public void print(@Nullable Object param) { + System.out.println("Printing " + param); + } + + @NotNull + public Object process() throws Exception { + Object result = doSomething(); + if (result == null) { + throw new Exception("Processing fail. Got a null response"); + } else { + return result; + } + } + + private Object doSomething() { + return null; + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/Preconditions.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/Preconditions.java new file mode 100644 index 0000000000..9d9633a13e --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/Preconditions.java @@ -0,0 +1,39 @@ +package com.baeldung.nulls; + +public class Preconditions { + + public void goodAccept(String one, String two, String three) { + if (one == null || two == null || three == null) { + throw new IllegalArgumentException(); + } + + process(one); + process(two); + process(three); + } + + public void badAccept(String one, String two, String three) { + if (one == null) { + throw new IllegalArgumentException(); + } else { + process(one); + } + + if (two == null) { + throw new IllegalArgumentException(); + } else { + process(two); + } + + if (three == null) { + throw new IllegalArgumentException(); + } else { + process(three); + } + + } + + private void process(String one) { + } + +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/PrimitivesAndWrapper.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/PrimitivesAndWrapper.java new file mode 100644 index 0000000000..c75918c486 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/PrimitivesAndWrapper.java @@ -0,0 +1,21 @@ +package com.baeldung.nulls; + +public class PrimitivesAndWrapper { + + public static int primitiveSum(int a, int b) { + return a + b; + } + + public static Integer wrapperSum(Integer a, Integer b) { + return a + b; + } + + public static Integer goodSum(Integer a, Integer b) { + if (a != null && b != null) { + return a + b; + } else { + throw new IllegalArgumentException(); + } + } + +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingLombok.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingLombok.java new file mode 100644 index 0000000000..73db0742c8 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingLombok.java @@ -0,0 +1,10 @@ +package com.baeldung.nulls; + +import lombok.NonNull; + +public class UsingLombok { + + public void accept(@NonNull Object param){ + System.out.println(param); + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingObjects.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingObjects.java new file mode 100644 index 0000000000..5384edee5e --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingObjects.java @@ -0,0 +1,11 @@ +package com.baeldung.nulls; + +import java.util.Objects; + +public class UsingObjects { + + public void accept(Object param) { + Objects.requireNonNull(param); + // doSomething() + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingOptional.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingOptional.java new file mode 100644 index 0000000000..6c17290a72 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingOptional.java @@ -0,0 +1,27 @@ +package com.baeldung.nulls; + +import java.util.Optional; + +public class UsingOptional { + + public Optional process(boolean processed) { + + String response = doSomething(processed); + + if (response == null) { + return Optional.empty(); + } + + return Optional.of(response); + } + + private String doSomething(boolean processed) { + + if (processed) { + return "passed"; + } else { + return null; + } + } + +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingStringUtils.java b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingStringUtils.java new file mode 100644 index 0000000000..c7c73b73eb --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/nulls/UsingStringUtils.java @@ -0,0 +1,22 @@ +package com.baeldung.nulls; + +import org.apache.commons.lang3.StringUtils; + +public class UsingStringUtils { + + public void accept(String param) { + if (StringUtils.isNotEmpty(param)) { + System.out.println(param); + } else { + throw new IllegalArgumentException(); + } + } + + public void acceptOnlyNonBlank(String param) { + if (StringUtils.isNotBlank(param)) { + System.out.println(param); + } else { + throw new IllegalArgumentException(); + } + } +} diff --git a/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/PrimitivesAndWrapperUnitTest.java b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/PrimitivesAndWrapperUnitTest.java new file mode 100644 index 0000000000..49655619f6 --- /dev/null +++ b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/PrimitivesAndWrapperUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.nulls; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class PrimitivesAndWrapperUnitTest { + + @Test + public void givenBothArgsNonNull_whenCallingWrapperSum_thenReturnSum() { + + Integer sum = PrimitivesAndWrapper.wrapperSum(0, 0); + + assertEquals(0, sum.intValue()); + } + + @Test() + public void givenOneArgIsNull_whenCallingWrapperSum_thenThrowNullPointerException() { + assertThrows(NullPointerException.class, () -> PrimitivesAndWrapper.wrapperSum(null, 2)); + } + + @Test() + public void givenBothArgsNull_whenCallingWrapperSum_thenThrowNullPointerException() { + assertThrows(NullPointerException.class, () -> PrimitivesAndWrapper.wrapperSum(null, null)); + } + + @Test() + public void givenOneArgNull_whenCallingGoodSum_thenThrowIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> PrimitivesAndWrapper.goodSum(null, 2)); + } + + + +} \ No newline at end of file diff --git a/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingLombokUnitTest.java b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingLombokUnitTest.java new file mode 100644 index 0000000000..b322344aba --- /dev/null +++ b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingLombokUnitTest.java @@ -0,0 +1,24 @@ +package com.baeldung.nulls; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class UsingLombokUnitTest { + + private UsingLombok classUnderTest; + + @BeforeEach + public void setup() { + classUnderTest = new UsingLombok(); + } + + @Test + public void whenNullArg_thenThrowNullPointerException() { + + assertThrows(NullPointerException.class, () -> classUnderTest.accept(null)); + + } + +} \ No newline at end of file diff --git a/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingObjectsUnitTest.java b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingObjectsUnitTest.java new file mode 100644 index 0000000000..e1f5a288e6 --- /dev/null +++ b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingObjectsUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.nulls; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class UsingObjectsUnitTest { + + private UsingObjects classUnderTest; + + @BeforeEach + public void setup() { + classUnderTest = new UsingObjects(); + } + + @Test + public void whenArgIsNull_thenThrowException() { + + assertThrows(NullPointerException.class, () -> classUnderTest.accept(null)); + } + + @Test + public void whenArgIsNonNull_thenDoesNotThrowException() { + + assertDoesNotThrow(() -> classUnderTest.accept("test ")); + } + +} \ No newline at end of file diff --git a/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingOptionalUnitTest.java b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingOptionalUnitTest.java new file mode 100644 index 0000000000..8f896cedfa --- /dev/null +++ b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingOptionalUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.nulls; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class UsingOptionalUnitTest { + + private UsingOptional classUnderTest; + + @BeforeEach + public void setup() { + classUnderTest = new UsingOptional(); + } + + @Test + public void whenArgIsFalse_thenReturnEmptyResponse() { + + Optional result = classUnderTest.process(false); + + assertFalse(result.isPresent()); + } + + @Test + public void whenArgIsTrue_thenReturnValidResponse() { + + Optional result = classUnderTest.process(true); + + assertTrue(result.isPresent()); + } + + @Test + public void whenArgIsFalse_thenChainResponseAndThrowException() { + + assertThrows(Exception.class, () -> classUnderTest.process(false).orElseThrow(() -> new Exception())); + } +} \ No newline at end of file diff --git a/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingStringUtilsUnitTest.java b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingStringUtilsUnitTest.java new file mode 100644 index 0000000000..f7c51a7dc5 --- /dev/null +++ b/patterns/design-patterns-2/src/test/java/com/baeldung/nulls/UsingStringUtilsUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.nulls; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class UsingStringUtilsUnitTest { + + private UsingStringUtils classUnderTest; + + @BeforeEach + public void setup() { + classUnderTest = new UsingStringUtils(); + } + + @Test + public void givenArgIsNull_whenCallingAccept_throwIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> classUnderTest.accept(null)); + } + + @Test + public void givenArgIsEmpty_whenCallingAccept_throwIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> classUnderTest.accept("")); + } + + @Test + public void givenArgIsNull_whenCallingAcceptOnlyNonBlank_throwIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> classUnderTest.acceptOnlyNonBlank(null)); + } + + @Test + public void givenArgIsEmpty_whenCallingAcceptOnlyNonBlank_throwIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> classUnderTest.acceptOnlyNonBlank("")); + } + + @Test + public void givenArgIsBlank_whenCallingAcceptOnlyNonBlank_throwIllegalArgumentException() { + assertThrows(IllegalArgumentException.class, () -> classUnderTest.acceptOnlyNonBlank(" ")); + } + +} \ No newline at end of file From ee06fce6f83f098325a5369242d138ccd9daab8b Mon Sep 17 00:00:00 2001 From: TINO Date: Fri, 29 Mar 2019 11:08:14 +0300 Subject: [PATCH 476/496] BAEL - 2829 Fixed the compilation error --- .../dao/repositories/EmployeeRepository.java | 4 +-- .../EmployeeRepositoryIntegrationTest.java | 28 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/EmployeeRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/EmployeeRepository.java index c6b75e5994..6185185791 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/EmployeeRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/dao/repositories/EmployeeRepository.java @@ -2,8 +2,8 @@ package com.baeldung.dao.repositories; import org.springframework.data.jpa.repository.JpaRepository; -import com.baeldung.domain.Person; +import com.baeldung.domain.Employee; -public interface PersonRepository extends JpaRepository { +public interface EmployeeRepository extends JpaRepository { } diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/EmployeeRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/EmployeeRepositoryIntegrationTest.java index d2e3ac67a0..13ceb702d2 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/EmployeeRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/dao/repositories/EmployeeRepositoryIntegrationTest.java @@ -8,32 +8,32 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.domain.Person; +import com.baeldung.domain.Employee; @RunWith(SpringRunner.class) @DataJpaTest -public class PersonRepositoryIntegrationTest { +public class EmployeeRepositoryIntegrationTest { - private static final Person PERSON1 = new Person(1L, "John", "Doe"); - private static final Person PERSON2 = new Person(2L, "Alice", "Bob"); + private static final Employee EMPLOYEE1 = new Employee(1L, "John"); + private static final Employee EMPLOYEE2 = new Employee(2L, "Alice"); @Autowired - private PersonRepository personRepository; + private EmployeeRepository employeeRepository; @Test - public void givenPersonEntity_whenInsertWithSave_ThenPersonIsPersisted() { - personRepository.save(PERSON1); - assertPersonPersisted(PERSON1); + public void givenEmployeeEntity_whenInsertWithSave_ThenEmployeeIsPersisted() { + employeeRepository.save(EMPLOYEE1); + assertEmployeePersisted(EMPLOYEE1); } @Test - public void givenPersonEntity_whenInsertWithSaveAndFlush_ThenPersonIsPersisted() { - personRepository.saveAndFlush(PERSON2); - assertPersonPersisted(PERSON2); + public void givenEmployeeEntity_whenInsertWithSaveAndFlush_ThenEmployeeIsPersisted() { + employeeRepository.saveAndFlush(EMPLOYEE2); + assertEmployeePersisted(EMPLOYEE2); } - private void assertPersonPersisted(Person input) { - Person person = personRepository.getOne(input.getId()); - assertThat(person).isNotNull(); + private void assertEmployeePersisted(Employee input) { + Employee employee = employeeRepository.getOne(input.getId()); + assertThat(employee).isNotNull(); } } From 9aad2a92744809f1871a65b59ded81ad2d7a6f68 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Fri, 29 Mar 2019 19:06:03 +0800 Subject: [PATCH 477/496] Update README.md --- core-java-9/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-9/README.md b/core-java-9/README.md index a423f0cb14..e2bea52e2d 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -28,5 +28,4 @@ - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) - [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation) - [Java 9 Process API Improvements](https://www.baeldung.com/java-9-process-api) -- [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) From 78b367345f6a3624b2086ecf1bdcf1416522995d Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Fri, 29 Mar 2019 19:06:35 +0800 Subject: [PATCH 478/496] Update README.md --- core-java-9/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/core-java-9/README.md b/core-java-9/README.md index e2bea52e2d..2477a38c00 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -27,5 +27,4 @@ - [Immutable Set in Java](https://www.baeldung.com/java-immutable-set) - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) - [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation) -- [Java 9 Process API Improvements](https://www.baeldung.com/java-9-process-api) From d60f90491aa2124db14b062727c144215417fb42 Mon Sep 17 00:00:00 2001 From: sheryllresulta <48046330+sheryllresulta@users.noreply.github.com> Date: Fri, 29 Mar 2019 19:09:13 +0800 Subject: [PATCH 479/496] Update README.md --- json/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/json/README.md b/json/README.md index 3670b4b9ad..7ef4cc9b01 100644 --- a/json/README.md +++ b/json/README.md @@ -12,5 +12,4 @@ - [Introduction to the JSON Binding API (JSR 367) in Java](http://www.baeldung.com/java-json-binding-api) - [Get a Value by Key in a JSONArray](https://www.baeldung.com/java-jsonarray-get-value-by-key) - [Iterating Over an Instance of org.json.JSONObject](https://www.baeldung.com/jsonobject-iteration) -- [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections) - [Escape JSON String in Java](https://www.baeldung.com/java-json-escaping) From b8af6bec2ba501375dfddbade4a1e2b4d4979216 Mon Sep 17 00:00:00 2001 From: Loredana Date: Fri, 29 Mar 2019 23:40:03 +0200 Subject: [PATCH 480/496] fix multiple sql files test --- ...Test.java => UserRepositoryMultipleSqlFilesIntTest.java} | 6 ++++-- .../application/tests/UserRepositoryIntegrationTest.java | 1 + .../test/resources/application-multiplesqlfiles.properties | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) rename persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/{UserRepositoryIntegrationTest.java => UserRepositoryMultipleSqlFilesIntTest.java} (79%) create mode 100644 persistence-modules/spring-boot-persistence/src/test/resources/application-multiplesqlfiles.properties diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/UserRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/UserRepositoryMultipleSqlFilesIntTest.java similarity index 79% rename from persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/UserRepositoryIntegrationTest.java rename to persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/UserRepositoryMultipleSqlFilesIntTest.java index 8ec1520495..f1f6e85d8c 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/boot/test/UserRepositoryMultipleSqlFilesIntTest.java @@ -4,6 +4,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.boot.domain.User; @@ -18,7 +19,8 @@ import static org.assertj.core.api.Assertions.assertThat; */ @RunWith(SpringRunner.class) @DataJpaTest -public class UserRepositoryIntegrationTest { +@ActiveProfiles("multiplesqlfiles") +public class UserRepositoryMultipleSqlFilesIntTest { @Autowired private UserRepository userRepository; @@ -26,7 +28,7 @@ public class UserRepositoryIntegrationTest { public void givenTwoImportFilesWhenFindAllShouldReturnSixUsers() { Collection users = userRepository.findAll(); - assertThat(users.size()).isEqualTo(3); + assertThat(users.size()).isEqualTo(6); } } diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/application/tests/UserRepositoryIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/application/tests/UserRepositoryIntegrationTest.java index 597628c5d4..e9824fce44 100644 --- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/application/tests/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/springbootdatasourceconfig/application/tests/UserRepositoryIntegrationTest.java @@ -25,6 +25,7 @@ public class UserRepositoryIntegrationTest { userRepository.save(new User("Bob", "bob@domain.com")); List users = (List) userRepository.findAll(); + // 2 additional users are saved in the CommandLineRunner bean assertThat(users.size()).isEqualTo(3); } } diff --git a/persistence-modules/spring-boot-persistence/src/test/resources/application-multiplesqlfiles.properties b/persistence-modules/spring-boot-persistence/src/test/resources/application-multiplesqlfiles.properties new file mode 100644 index 0000000000..06efc25f38 --- /dev/null +++ b/persistence-modules/spring-boot-persistence/src/test/resources/application-multiplesqlfiles.properties @@ -0,0 +1 @@ +spring.jpa.properties.hibernate.hbm2ddl.import_files=import_active_users.sql,import_inactive_users.sql \ No newline at end of file From 6ce8073fde845a0d38fad1c98a5cba95bcca1586 Mon Sep 17 00:00:00 2001 From: Kacper Koza Date: Sat, 30 Mar 2019 00:35:26 +0100 Subject: [PATCH 481/496] BAEL-2780 | spock extensions --- .../groovy-spock/report-2019-03-29.json | 402 ++++++++++++++++++ .../groovy/extensions/CustomTitleTest.groovy | 20 + .../groovy/extensions/IgnoreIfTest.groovy | 12 + .../groovy/extensions/IgnoreRestTest.groovy | 16 + .../test/groovy/extensions/IgnoreTest.groovy | 20 + .../test/groovy/extensions/IssueTest.groovy | 25 ++ .../extensions/PendingFeatureTest.groovy | 11 + .../groovy/extensions/RequiresTest.groovy | 14 + .../RestoreSystemPropertiesTest.groovy | 18 + .../test/groovy/extensions/RetryTest.groovy | 20 + .../src/test/groovy/extensions/SeeTest.groovy | 20 + .../groovy/extensions/StackTraceTest.groovy | 13 + .../groovy/extensions/StepwiseTest.groovy | 14 + .../test/groovy/extensions/SubjectTest.groovy | 13 + .../test/groovy/extensions/TimeoutTest.groovy | 24 ++ .../src/test/resources/SpockConfig.groovy | 27 ++ 16 files changed, 669 insertions(+) create mode 100644 testing-modules/groovy-spock/report-2019-03-29.json create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/CustomTitleTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreIfTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreRestTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/IssueTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/PendingFeatureTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/RequiresTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/RestoreSystemPropertiesTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/RetryTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/SeeTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/StackTraceTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/StepwiseTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/SubjectTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/groovy/extensions/TimeoutTest.groovy create mode 100644 testing-modules/groovy-spock/src/test/resources/SpockConfig.groovy diff --git a/testing-modules/groovy-spock/report-2019-03-29.json b/testing-modules/groovy-spock/report-2019-03-29.json new file mode 100644 index 0000000000..85f0b261fb --- /dev/null +++ b/testing-modules/groovy-spock/report-2019-03-29.json @@ -0,0 +1,402 @@ +loadLogFile([{ + "package": "mocks", + "name": "ExampleSpockTest", + "start": 1553898111660, + "features": [ + { + "name": "should calculate character occurrences in given string", + "start": 1553898111662, + "end": 1553898111699, + "result": "passed", + "attachments": [ + + ] + } + ], + "end": 1553898111709, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "mocks", + "name": "ItemServiceTest", + "start": 1553898111714, + "features": [ + { + "name": "should spy on EventPublisher method call", + "start": 1553898111714, + "output": [ + "I've published: item-id\n" + ], + "end": 1553898112250, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "should return items", + "start": 1553898112250, + "end": 1553898112260, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "should publish events about new non-empty saved offers", + "start": 1553898112260, + "end": 1553898112267, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "should return different items for different ids lists", + "start": 1553898112267, + "end": 1553898112280, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "should throw ExternalItemProviderException when ItemProvider fails", + "start": 1553898112281, + "end": 1553898112294, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "should return different items on subsequent call", + "start": 1553898112294, + "narrative": "When method is called for the first time\nThen empty list is returned\nWhen method is called for the second time\nThen item with id=1 is returned\nWhen method is called for the thirdtime\nThen item with id=2 is returned", + "end": 1553898112298, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "should return items sorted by name", + "start": 1553898112299, + "end": 1553898112307, + "result": "passed", + "attachments": [ + + ] + } + ], + "end": 1553898112310, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "FirstSpecification", + "name": "FirstSpecification", + "start": 1553898112314, + "features": [ + { + "name": "Should verify notify was called", + "start": 1553898112314, + "end": 1553898112324, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "Should return true value for mock", + "start": 1553898112325, + "end": 1553898112344, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "Should return default value for mock", + "start": 1553898112344, + "end": 1553898112347, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "numbers to the power of two", + "start": 1553898112347, + "end": 1553898112358, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "Should get an index out of bounds when removing a non-existent item", + "start": 1553898112358, + "end": 1553898112364, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "Should be able to remove from list", + "start": 1553898112364, + "end": 1553898112366, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "two plus two should equal four", + "start": 1553898112366, + "end": 1553898112368, + "result": "passed", + "attachments": [ + + ] + }, + { + "name": "one plus one should equal two", + "start": 1553898112368, + "end": 1553898112391, + "result": "passed", + "attachments": [ + + ] + } + ], + "end": 1553898112394, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "IgnoreTest", + "start": 1553898112395, + "end": 1553898112395, + "result": "skipped" +}]) + +loadLogFile([{ + "package": "extensions", + "name": "RetryTest", + "start": 1553898112403, + "end": 1553898112405, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "This title is easy to read for humans", + "start": 1553898112407, + "end": 1553898112408, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "SeeTest", + "start": 1553898112409, + "end": 1553898112411, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "StepwiseTest", + "start": 1553898112422, + "end": 1553898112423, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "NarrativeDescriptionTest", + "start": 1553898112427, + "narrative": "as a user\n i want to save favourite items \n and then get the list of them", + "end": 1553898112433, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "SubjectTest", + "start": 1553898112434, + "end": 1553898112436, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "IgnoreRestTest", + "start": 1553898112437, + "end": 1553898112437, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "StackTraceTest", + "start": 1553898112438, + "features": [ + { + "name": "stacktrace", + "start": 1553898112438, + "exceptions": [ + "java.lang.RuntimeException: blabla\n\tat extensions.StackTraceTest.stacktrace(StackTraceTest.groovy:10)\n" + ], + "end": 1553898112455, + "result": "failed", + "attachments": [ + + ] + } + ], + "end": 1553898112470, + "result": "failed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "IgnoreIfTest", + "start": 1553898112471, + "end": 1553898112472, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "RequiresTest", + "start": 1553898112473, + "features": [ + { + "name": "I will run only on Windows", + "start": 1553898112474, + "end": 1553898112474, + "result": "skipped" + } + ], + "end": 1553898112476, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "IssueTest", + "start": 1553898112477, + "features": [ + { + "name": "I'm using Spock configuration file", + "start": 1553898112477, + "tags": [ + { + "name": "Bug LO-1000", + "key": "issue", + "value": "LO-1000", + "url": "http:\/\/jira.org\/issues\/LO-1000" + } + ], + "end": 1553898112489, + "result": "passed", + "attachments": [ + + ] + } + ], + "end": 1553898112490, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "TimeoutTest", + "start": 1553898112491, + "features": [ + { + "name": "I will fail after 200 millis", + "start": 1553898112491, + "end": 1553898112514, + "result": "passed", + "attachments": [ + + ] + } + ], + "end": 1553898112517, + "result": "passed", + "attachments": [ + + ] +}]) + +loadLogFile([{ + "package": "extensions", + "name": "RestoreSystemPropertiesTest", + "start": 1553898112518, + "features": [ + { + "name": "all environment variables will be saved before execution and restored after tests", + "start": 1553898112518, + "end": 1553898112532, + "result": "passed", + "attachments": [ + + ] + } + ], + "end": 1553898112539, + "result": "passed", + "attachments": [ + + ] +}]) + diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/CustomTitleTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/CustomTitleTest.groovy new file mode 100644 index 0000000000..11a5fb0eb9 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/CustomTitleTest.groovy @@ -0,0 +1,20 @@ +package extensions + +import spock.lang.Narrative +import spock.lang.Specification +import spock.lang.Title + + +@Title("""This title is easy to read for humans""") +class CustomTitleTest extends Specification { + +} + +@Narrative(""" + as a user + i want to save favourite items + and then get the list of them +""") +class NarrativeDescriptionTest extends Specification { + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreIfTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreIfTest.groovy new file mode 100644 index 0000000000..91da2ff1ec --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreIfTest.groovy @@ -0,0 +1,12 @@ +package extensions + +import spock.lang.IgnoreIf +import spock.lang.Specification + + +class IgnoreIfTest extends Specification { + + @IgnoreIf({System.getProperty("os.name").contains("windows")}) + def "I won't run on windows"() { } + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreRestTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreRestTest.groovy new file mode 100644 index 0000000000..dead2c7393 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreRestTest.groovy @@ -0,0 +1,16 @@ +package extensions + +import spock.lang.IgnoreRest +import spock.lang.Specification + + +class IgnoreRestTest extends Specification { + + def "I won't run"() { } + + @IgnoreRest + def 'I will run'() { } + + def "I won't run too"() { } + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreTest.groovy new file mode 100644 index 0000000000..9af5708ae2 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreTest.groovy @@ -0,0 +1,20 @@ +package extensions + +import spock.lang.Ignore +import spock.lang.Specification + +@Ignore +class IgnoreTest extends Specification { + + @Ignore + def "I won't be executed"() { + expect: + true + } + + def 'Example test'() { + expect: + true + } + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/IssueTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/IssueTest.groovy new file mode 100644 index 0000000000..56e0f09bf1 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/IssueTest.groovy @@ -0,0 +1,25 @@ +package extensions + +import spock.lang.Issue +import spock.lang.Specification + + +class IssueTest extends Specification { + + + @Issue("http://jira.org/issues/LO-531") + def 'single issue'() { + } + + @Issue(["http://jira.org/issues/LO-531", "http://jira.org/issues/LO-123"]) + def 'multiple issues'() { + } + + @Issue("LO-1000") + def "I'm using Spock configuration file"() { + expect: + true + } + + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/PendingFeatureTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/PendingFeatureTest.groovy new file mode 100644 index 0000000000..59bd99ceb8 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/PendingFeatureTest.groovy @@ -0,0 +1,11 @@ +package extensions + +import spock.lang.PendingFeature + +class PendingFeatureTest { + + @PendingFeature + def 'test for not implemented yet feature'() { + + } +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/RequiresTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/RequiresTest.groovy new file mode 100644 index 0000000000..c384c3786b --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/RequiresTest.groovy @@ -0,0 +1,14 @@ +package extensions + +import spock.lang.Requires +import spock.lang.Specification + + +class RequiresTest extends Specification { + + @Requires({ System.getProperty("os.name").contains("windows") }) + def "I will run only on Windows"() { + expect: + true + } +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/RestoreSystemPropertiesTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/RestoreSystemPropertiesTest.groovy new file mode 100644 index 0000000000..824e88d84e --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/RestoreSystemPropertiesTest.groovy @@ -0,0 +1,18 @@ +package extensions + +import spock.lang.Specification +import spock.util.environment.RestoreSystemProperties + + +class RestoreSystemPropertiesTest extends Specification { + + @RestoreSystemProperties + def 'all environment variables will be saved before execution and restored after tests'() { + given: + System.setProperty('os.name', 'Mac OS') + + expect: + true + } + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/RetryTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/RetryTest.groovy new file mode 100644 index 0000000000..a07ebae851 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/RetryTest.groovy @@ -0,0 +1,20 @@ +package extensions + +import spock.lang.Retry +import spock.lang.Specification + +@Retry +class RetryTest extends Specification { + + @Retry + def 'I will retry three times'() { } + + @Retry(exceptions = [RuntimeException]) + def 'I will retry only on RuntimeException'() { } + + @Retry(condition = { failure.message.contains('error') }) + def 'I will retry with a specific message'() { } + + @Retry(delay = 1000) + def 'I will retry after 1000 millis'() { } +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/SeeTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/SeeTest.groovy new file mode 100644 index 0000000000..50212ad136 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/SeeTest.groovy @@ -0,0 +1,20 @@ +package extensions + +import spock.lang.See +import spock.lang.Specification + + +class SeeTest extends Specification { + + + @See("https://example.org") + def 'Look at the reference'() { + + } + + @See(["https://example.org/first", "https://example.org/first"]) + def 'Look at the references'() { + + } + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/StackTraceTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/StackTraceTest.groovy new file mode 100644 index 0000000000..50012bd225 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/StackTraceTest.groovy @@ -0,0 +1,13 @@ +package extensions + +import org.junit.Ignore +import spock.lang.Specification + + +class StackTraceTest extends Specification { + + def 'stacktrace'() { +// expect: +// throw new RuntimeException("blabla") + } +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/StepwiseTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/StepwiseTest.groovy new file mode 100644 index 0000000000..1bf83ce84d --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/StepwiseTest.groovy @@ -0,0 +1,14 @@ +package extensions + +import spock.lang.Specification +import spock.lang.Stepwise + + +@Stepwise +class StepwiseTest extends Specification { + + def 'I will run as first'() { } + + def 'I will run as second'() { } + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/SubjectTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/SubjectTest.groovy new file mode 100644 index 0000000000..8474df0f14 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/SubjectTest.groovy @@ -0,0 +1,13 @@ +package extensions + +import mocks.ItemService +import spock.lang.Specification +import spock.lang.Subject + + +class SubjectTest extends Specification { + + @Subject + ItemService itemService // initialization here... + +} diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/TimeoutTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/TimeoutTest.groovy new file mode 100644 index 0000000000..0049d99806 --- /dev/null +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/TimeoutTest.groovy @@ -0,0 +1,24 @@ +package extensions + +import spock.lang.Specification +import spock.lang.Timeout + +import java.util.concurrent.TimeUnit + +@Timeout(5) +class TimeoutTest extends Specification { + + @Timeout(1) + def 'I have one second to finish'() { + + } + + def 'I will have 5 seconds timeout'() {} + + @Timeout(value = 200, unit = TimeUnit.SECONDS) + def 'I will fail after 200 millis'() { + expect: + true + } + +} diff --git a/testing-modules/groovy-spock/src/test/resources/SpockConfig.groovy b/testing-modules/groovy-spock/src/test/resources/SpockConfig.groovy new file mode 100644 index 0000000000..ed94e61cbf --- /dev/null +++ b/testing-modules/groovy-spock/src/test/resources/SpockConfig.groovy @@ -0,0 +1,27 @@ +import extensions.TimeoutTest +import spock.lang.Issue + +runner { + filterStackTrace true + + report { + issueNamePrefix 'Bug ' + issueUrlPrefix 'http://jira.org/issues/' + } + + optimizeRunOrder true + +// exclude TimeoutTest +// exclude { +// baseClass TimeoutTest +// annotation Issue +// } + + report { + enabled true + logFileDir '.' + logFileName 'report.json' + logFileSuffix new Date().format('yyyy-MM-dd') + } + +} From cd23e7c9057b470e4d064c9fec91e6a70fc5b019 Mon Sep 17 00:00:00 2001 From: Kacper Koza Date: Sat, 30 Mar 2019 00:36:29 +0100 Subject: [PATCH 482/496] master --- .../src/test/groovy/extensions/StackTraceTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/StackTraceTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/StackTraceTest.groovy index 50012bd225..00fa55e21e 100644 --- a/testing-modules/groovy-spock/src/test/groovy/extensions/StackTraceTest.groovy +++ b/testing-modules/groovy-spock/src/test/groovy/extensions/StackTraceTest.groovy @@ -6,7 +6,7 @@ import spock.lang.Specification class StackTraceTest extends Specification { - def 'stacktrace'() { + def 'stkacktrace'() { // expect: // throw new RuntimeException("blabla") } From 2eaf55fce3f9bd4efe567ec16038db4012f1e4f5 Mon Sep 17 00:00:00 2001 From: eric-martin Date: Fri, 29 Mar 2019 19:57:18 -0500 Subject: [PATCH 483/496] BAEL-1961: Fixed UserModelListener.onBeforeConvert() --- .../java/com/baeldung/mongodb/events/UserModelListener.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/events/UserModelListener.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/events/UserModelListener.java index 24b53f3d2d..2fe81f7ef4 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/events/UserModelListener.java +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/mongodb/events/UserModelListener.java @@ -21,7 +21,9 @@ public class UserModelListener extends AbstractMongoEventListener { @Override public void onBeforeConvert(BeforeConvertEvent event) { - event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME)); + if (event.getSource().getId() < 1) { + event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME)); + } } From 362525572eb04c8141d5547cfacb5759cf419efe Mon Sep 17 00:00:00 2001 From: Loredana Crusoveanu Date: Sat, 30 Mar 2019 13:57:02 +0200 Subject: [PATCH 484/496] Update README.md --- xml/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/xml/README.md b/xml/README.md index 9d889ef8e9..fb070100db 100644 --- a/xml/README.md +++ b/xml/README.md @@ -4,4 +4,3 @@ - [XML Libraries Support in Java](http://www.baeldung.com/java-xml-libraries) - [DOM parsing with Xerces](http://www.baeldung.com/java-xerces-dom-parsing) - [Write an org.w3.dom.Document to a File](https://www.baeldung.com/java-write-xml-document-file) -- [Convert XML to HTML](https://www.baeldung.com/) From b67a006020d5f3e43cb4c0a33e3d3af42e642986 Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Sat, 30 Mar 2019 13:01:00 -0300 Subject: [PATCH 485/496] BAEL-2789 - The Dependency Inversion Principle in Java (#6613) * Initial Commit * Added dip dipmodular modules to pom.xml * Delete pom.xml * Add pom.xml * Update pom.xml * Update pom.xml * Update pom.xml * Update Application.java * Update CustomerDaoUnitTest.java * Update CustomerServiceUnitTest.java * Update Application.java * Update CustomerDaoUnitTest.java * Update CustomerServiceUnitTest.java * Update CustomerDaoUnitTest.java * Update CustomerServiceUnitTest.java --- patterns/dip/pom.xml | 39 ++++++++++++++++ .../baeldung/dip/application/Application.java | 18 ++++++++ .../daoimplementations/SimpleCustomerDao.java | 28 +++++++++++ .../dip/daointerfaces/CustomerDao.java | 13 ++++++ .../com/baeldung/dip/entities/Customer.java | 19 ++++++++ .../dip/services/CustomerService.java | 23 ++++++++++ .../dip/tests/CustomerDaoUnitTest.java | 46 +++++++++++++++++++ .../dip/tests/CustomerServiceUnitTest.java | 46 +++++++++++++++++++ patterns/pom.xml | 7 +-- 9 files changed, 236 insertions(+), 3 deletions(-) create mode 100644 patterns/dip/pom.xml create mode 100644 patterns/dip/src/main/java/com/baeldung/dip/application/Application.java create mode 100644 patterns/dip/src/main/java/com/baeldung/dip/daoimplementations/SimpleCustomerDao.java create mode 100644 patterns/dip/src/main/java/com/baeldung/dip/daointerfaces/CustomerDao.java create mode 100644 patterns/dip/src/main/java/com/baeldung/dip/entities/Customer.java create mode 100644 patterns/dip/src/main/java/com/baeldung/dip/services/CustomerService.java create mode 100644 patterns/dip/src/test/java/com/baeldung/dip/tests/CustomerDaoUnitTest.java create mode 100644 patterns/dip/src/test/java/com/baeldung/dip/tests/CustomerServiceUnitTest.java diff --git a/patterns/dip/pom.xml b/patterns/dip/pom.xml new file mode 100644 index 0000000000..dac3f824f2 --- /dev/null +++ b/patterns/dip/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + com.baeldung.dip + dip + dip + 1.0-SNAPSHOT + + + com.baeldung + patterns + 1.0.0-SNAPSHOT + .. + + + + + junit + junit + 4.12 + test + + + org.assertj + assertj-core + 3.12.1 + test + + + + + UTF-8 + 11 + 11 + + + diff --git a/patterns/dip/src/main/java/com/baeldung/dip/application/Application.java b/patterns/dip/src/main/java/com/baeldung/dip/application/Application.java new file mode 100644 index 0000000000..8cc8901f70 --- /dev/null +++ b/patterns/dip/src/main/java/com/baeldung/dip/application/Application.java @@ -0,0 +1,18 @@ +package com.baeldung.dip.application; + +import com.baeldung.dip.daoimplementations.SimpleCustomerDao; +import com.baeldung.dip.entities.Customer; +import com.baeldung.dip.services.CustomerService; +import java.util.Map; +import java.util.HashMap; + +public class Application { + + public static void main(String[] args) { + Map customers = new HashMap<>(); + customers.put(1, new Customer("John")); + customers.put(2, new Customer("Susan")); + CustomerService customerService = new CustomerService(new SimpleCustomerDao(customers)); + customerService.findAll().forEach(System.out::println); + } +} diff --git a/patterns/dip/src/main/java/com/baeldung/dip/daoimplementations/SimpleCustomerDao.java b/patterns/dip/src/main/java/com/baeldung/dip/daoimplementations/SimpleCustomerDao.java new file mode 100644 index 0000000000..ea2bf3f00a --- /dev/null +++ b/patterns/dip/src/main/java/com/baeldung/dip/daoimplementations/SimpleCustomerDao.java @@ -0,0 +1,28 @@ +package com.baeldung.dip.daoimplementations; + +import com.baeldung.dip.entities.Customer; +import com.baeldung.dip.daointerfaces.CustomerDao; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class SimpleCustomerDao implements CustomerDao { + + private Map customers = new HashMap<>(); + + public SimpleCustomerDao(Map customers) { + this.customers = customers; + } + + @Override + public Optional findById(int id) { + return Optional.ofNullable(customers.get(id)); + } + + @Override + public List findAll() { + return new ArrayList<>(customers.values()); + } +} diff --git a/patterns/dip/src/main/java/com/baeldung/dip/daointerfaces/CustomerDao.java b/patterns/dip/src/main/java/com/baeldung/dip/daointerfaces/CustomerDao.java new file mode 100644 index 0000000000..8ea83673b0 --- /dev/null +++ b/patterns/dip/src/main/java/com/baeldung/dip/daointerfaces/CustomerDao.java @@ -0,0 +1,13 @@ +package com.baeldung.dip.daointerfaces; + +import com.baeldung.dip.entities.Customer; +import java.util.List; +import java.util.Optional; + +public interface CustomerDao { + + Optional findById(int id); + + List findAll(); + +} diff --git a/patterns/dip/src/main/java/com/baeldung/dip/entities/Customer.java b/patterns/dip/src/main/java/com/baeldung/dip/entities/Customer.java new file mode 100644 index 0000000000..f8d5d82102 --- /dev/null +++ b/patterns/dip/src/main/java/com/baeldung/dip/entities/Customer.java @@ -0,0 +1,19 @@ +package com.baeldung.dip.entities; + +public class Customer { + + private final String name; + + public Customer(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "Customer{" + "name=" + name + '}'; + } +} diff --git a/patterns/dip/src/main/java/com/baeldung/dip/services/CustomerService.java b/patterns/dip/src/main/java/com/baeldung/dip/services/CustomerService.java new file mode 100644 index 0000000000..4566186ced --- /dev/null +++ b/patterns/dip/src/main/java/com/baeldung/dip/services/CustomerService.java @@ -0,0 +1,23 @@ +package com.baeldung.dip.services; + +import com.baeldung.dip.daointerfaces.CustomerDao; +import com.baeldung.dip.entities.Customer; +import java.util.List; +import java.util.Optional; + +public class CustomerService { + + private final CustomerDao customerDao; + + public CustomerService(CustomerDao customerDao) { + this.customerDao = customerDao; + } + + public Optional findById(int id) { + return customerDao.findById(id); + } + + public List findAll() { + return customerDao.findAll(); + } +} diff --git a/patterns/dip/src/test/java/com/baeldung/dip/tests/CustomerDaoUnitTest.java b/patterns/dip/src/test/java/com/baeldung/dip/tests/CustomerDaoUnitTest.java new file mode 100644 index 0000000000..2a03822ce2 --- /dev/null +++ b/patterns/dip/src/test/java/com/baeldung/dip/tests/CustomerDaoUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.dip.tests; + +import com.baeldung.dip.daoimplementations.SimpleCustomerDao; +import com.baeldung.dip.daointerfaces.CustomerDao; +import com.baeldung.dip.entities.Customer; +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Before; +import org.junit.Test; + +public class CustomerDaoUnitTest { + + private CustomerDao customerDao; + + @Before + public void setUpCustomerDaoInstance() { + Map customers = new HashMap<>(); + customers.put(1, new Customer("John")); + customers.put(2, new Customer("Susan")); + customerDao = new SimpleCustomerDao(customers); + } + + @Test + public void givenCustomerDaoInstance_whenCalledFindById_thenCorrect() { + assertThat(customerDao.findById(1)).isInstanceOf(Optional.class); + } + + @Test + public void givenCustomerDaoInstance_whenCalledFindAll_thenCorrect() { + assertThat(customerDao.findAll()).isInstanceOf(List.class); + } + + @Test + public void givenCustomerDaoInstance_whenCalledFindByIdWithNullCustomer_thenCorrect() { + Map customers = new HashMap(); + customers.put(1, null); + CustomerDao customerDaoObject = new SimpleCustomerDao(customers); + + Customer customer = customerDaoObject.findById(1).orElseGet(() -> new Customer("Non-existing customer")); + + assertThat(customer.getName()).isEqualTo("Non-existing customer"); + } +} diff --git a/patterns/dip/src/test/java/com/baeldung/dip/tests/CustomerServiceUnitTest.java b/patterns/dip/src/test/java/com/baeldung/dip/tests/CustomerServiceUnitTest.java new file mode 100644 index 0000000000..5ffd6fad51 --- /dev/null +++ b/patterns/dip/src/test/java/com/baeldung/dip/tests/CustomerServiceUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.dip.tests; + +import com.baeldung.dip.daoimplementations.SimpleCustomerDao; +import com.baeldung.dip.entities.Customer; +import com.baeldung.dip.services.CustomerService; +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Before; +import org.junit.Test; + +public class CustomerServiceUnitTest { + + private CustomerService customerService; + + @Before + public void setUpCustomerServiceInstance() { + Map customers = new HashMap<>(); + customers.put(1, new Customer("John")); + customers.put(2, new Customer("Susan")); + customerService = new CustomerService(new SimpleCustomerDao(customers)); + } + + @Test + public void givenCustomerServiceInstance_whenCalledFindById_thenCorrect() { + assertThat(customerService.findById(1)).isInstanceOf(Optional.class); + } + + @Test + public void givenCustomerServiceInstance_whenCalledFindAll_thenCorrect() { + assertThat(customerService.findAll()).isInstanceOf(List.class); + } + + @Test + public void givenCustomerServiceInstance_whenCalledFindByIdWithNullCustomer_thenCorrect() { + Map customers = new HashMap<>(); + customers.put(1, null); + customerService = new CustomerService(new SimpleCustomerDao(customers)); + + Customer customer = customerService.findById(1).orElseGet(() -> new Customer("Non-existing customer")); + + assertThat(customer.getName()).isEqualTo("Non-existing customer"); + } +} diff --git a/patterns/pom.xml b/patterns/pom.xml index 111e72b9ca..bf302a7a74 100644 --- a/patterns/pom.xml +++ b/patterns/pom.xml @@ -1,10 +1,10 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 patterns pom - patterns + patterns com.baeldung @@ -19,6 +19,7 @@ design-patterns design-patterns-2 solid + dip @@ -55,4 +56,4 @@ 9.4.0.v20161208 - \ No newline at end of file + From 5754bb33100da75623c3774233fa9eab73e367c8 Mon Sep 17 00:00:00 2001 From: Alejandro Gervasio Date: Sat, 30 Mar 2019 13:01:53 -0300 Subject: [PATCH 486/496] Initial Commit (#6614) --- .../daoimplementations/SimpleCustomerDao.java | 30 +++++++++++++++++++ .../module-info.java | 6 ++++ .../com/baeldung/dip/daos/CustomerDao.java | 13 ++++++++ .../com.baeldung.dip.daos/module-info.java | 4 +++ .../com/baeldung/dip/entities/Customer.java | 19 ++++++++++++ .../module-info.java | 3 ++ .../baeldung/dip/mainapp/MainApplication.java | 17 +++++++++++ .../com.baeldung.dip.mainapp/module-info.java | 7 +++++ .../dip/services/CustomerService.java | 23 ++++++++++++++ .../module-info.java | 6 ++++ 10 files changed, 128 insertions(+) create mode 100644 patterns/dipmodular/com.baeldung.dip.daoimplementations/com/baeldung/dip/daoimplementations/SimpleCustomerDao.java create mode 100644 patterns/dipmodular/com.baeldung.dip.daoimplementations/module-info.java create mode 100644 patterns/dipmodular/com.baeldung.dip.daos/com/baeldung/dip/daos/CustomerDao.java create mode 100644 patterns/dipmodular/com.baeldung.dip.daos/module-info.java create mode 100644 patterns/dipmodular/com.baeldung.dip.entities/com/baeldung/dip/entities/Customer.java create mode 100644 patterns/dipmodular/com.baeldung.dip.entities/module-info.java create mode 100644 patterns/dipmodular/com.baeldung.dip.mainapp/com/baeldung/dip/mainapp/MainApplication.java create mode 100644 patterns/dipmodular/com.baeldung.dip.mainapp/module-info.java create mode 100644 patterns/dipmodular/com.baeldung.dip.services/com/baeldung/dip/services/CustomerService.java create mode 100644 patterns/dipmodular/com.baeldung.dip.services/module-info.java diff --git a/patterns/dipmodular/com.baeldung.dip.daoimplementations/com/baeldung/dip/daoimplementations/SimpleCustomerDao.java b/patterns/dipmodular/com.baeldung.dip.daoimplementations/com/baeldung/dip/daoimplementations/SimpleCustomerDao.java new file mode 100644 index 0000000000..ef6482ecc7 --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.daoimplementations/com/baeldung/dip/daoimplementations/SimpleCustomerDao.java @@ -0,0 +1,30 @@ +package com.baeldung.dip.daoimplementations; + +import com.baeldung.dip.daos.CustomerDao; +import com.baeldung.dip.entities.Customer; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class SimpleCustomerDao implements CustomerDao { + + private Map customers = new HashMap<>(); + + public SimpleCustomerDao() { + + } + + public SimpleCustomerDao(Map customers) { + this.customers = customers; + } + + @Override + public Optional findById(int id) { + return Optional.ofNullable(customers.get(id)); + } + + @Override + public List findAll() { + return new ArrayList<>(customers.values()); + } +} diff --git a/patterns/dipmodular/com.baeldung.dip.daoimplementations/module-info.java b/patterns/dipmodular/com.baeldung.dip.daoimplementations/module-info.java new file mode 100644 index 0000000000..1df40ce3b8 --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.daoimplementations/module-info.java @@ -0,0 +1,6 @@ +module com.baeldung.dip.daoimplementations { + requires com.baeldung.dip.entities; + requires com.baeldung.dip.daos; + provides com.baeldung.dip.daos.CustomerDao with com.baeldung.dip.daoimplementations.SimpleCustomerDao; + exports com.baeldung.dip.daoimplementations; +} diff --git a/patterns/dipmodular/com.baeldung.dip.daos/com/baeldung/dip/daos/CustomerDao.java b/patterns/dipmodular/com.baeldung.dip.daos/com/baeldung/dip/daos/CustomerDao.java new file mode 100644 index 0000000000..b0080dd15e --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.daos/com/baeldung/dip/daos/CustomerDao.java @@ -0,0 +1,13 @@ +package com.baeldung.dip.daos; + +import com.baeldung.dip.entities.Customer; +import java.util.Map; +import java.util.Optional; + +public interface CustomerDao { + + Optional findById(int id); + + List findAll(); + +} diff --git a/patterns/dipmodular/com.baeldung.dip.daos/module-info.java b/patterns/dipmodular/com.baeldung.dip.daos/module-info.java new file mode 100644 index 0000000000..897c6168a1 --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.daos/module-info.java @@ -0,0 +1,4 @@ +module com.baeldung.dip.daos { + requires com.baeldung.dip.entities; + exports com.baeldung.dip.daos; +} diff --git a/patterns/dipmodular/com.baeldung.dip.entities/com/baeldung/dip/entities/Customer.java b/patterns/dipmodular/com.baeldung.dip.entities/com/baeldung/dip/entities/Customer.java new file mode 100644 index 0000000000..f8d5d82102 --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.entities/com/baeldung/dip/entities/Customer.java @@ -0,0 +1,19 @@ +package com.baeldung.dip.entities; + +public class Customer { + + private final String name; + + public Customer(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return "Customer{" + "name=" + name + '}'; + } +} diff --git a/patterns/dipmodular/com.baeldung.dip.entities/module-info.java b/patterns/dipmodular/com.baeldung.dip.entities/module-info.java new file mode 100644 index 0000000000..da8c1ccaee --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.entities/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.dip.entities { + exports com.baeldung.dip.entities; +} diff --git a/patterns/dipmodular/com.baeldung.dip.mainapp/com/baeldung/dip/mainapp/MainApplication.java b/patterns/dipmodular/com.baeldung.dip.mainapp/com/baeldung/dip/mainapp/MainApplication.java new file mode 100644 index 0000000000..8972dc3994 --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.mainapp/com/baeldung/dip/mainapp/MainApplication.java @@ -0,0 +1,17 @@ +package com.baeldung.dip.mainapp; + +import com.baeldung.dip.daoimplementations.MapCustomerDao; +import com.baeldung.dip.entities.Customer; +import com.baeldung.dip.services.CustomerService; +import java.util.HashMap; + +public class MainApplication { + + public static void main(String args[]) { + var customers = new HashMap(); + customers.put(1, new Customer("John")); + customers.put(2, new Customer("Susan")); + CustomerService customerService = new CustomerService(new SimpleCustomerDao(customers)); + customerService.findAll().forEach(System.out::println); + } +} diff --git a/patterns/dipmodular/com.baeldung.dip.mainapp/module-info.java b/patterns/dipmodular/com.baeldung.dip.mainapp/module-info.java new file mode 100644 index 0000000000..466306334a --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.mainapp/module-info.java @@ -0,0 +1,7 @@ +module com.baeldung.dip.mainapp { + requires com.baeldung.dip.entities; + requires com.baeldung.dip.daos; + requires com.baeldung.dip.daoimplementations; + requires com.baeldung.dip.services; + exports com.baeldung.dip.mainapp; +} diff --git a/patterns/dipmodular/com.baeldung.dip.services/com/baeldung/dip/services/CustomerService.java b/patterns/dipmodular/com.baeldung.dip.services/com/baeldung/dip/services/CustomerService.java new file mode 100644 index 0000000000..39955abdaf --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.services/com/baeldung/dip/services/CustomerService.java @@ -0,0 +1,23 @@ +package com.baeldung.dip.services; + +import com.baeldung.dip.daos.CustomerDao; +import com.baeldung.dip.entities.Customer; +import java.util.Map; +import java.util.Optional; + +public class CustomerService { + + private final CustomerDao customerDao; + + public CustomerService(CustomerDao customerDao) { + this.customerDao = customerDao; + } + + public Optional findById(int id) { + return customerDao.findById(id); + } + + public List findAll() { + return customerDao.findAll(); + } +} diff --git a/patterns/dipmodular/com.baeldung.dip.services/module-info.java b/patterns/dipmodular/com.baeldung.dip.services/module-info.java new file mode 100644 index 0000000000..8e59cd7abe --- /dev/null +++ b/patterns/dipmodular/com.baeldung.dip.services/module-info.java @@ -0,0 +1,6 @@ +module com.baeldung.dip.services { + requires com.baeldung.dip.entities; + requires com.baeldung.dip.daos; + uses com.baeldung.dip.daos.CustomerDao; + exports com.baeldung.dip.services; +} From baf08e07c8d335b89a7dda3575ec0f6b1e84fd95 Mon Sep 17 00:00:00 2001 From: Loredana Date: Sun, 31 Mar 2019 14:34:03 +0300 Subject: [PATCH 487/496] fix boot validation test --- .../{tests => application}/UserControllerIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename spring-boot/src/test/java/com/baeldung/validation/{tests => application}/UserControllerIntegrationTest.java (96%) diff --git a/spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java b/spring-boot/src/test/java/com/baeldung/validation/application/UserControllerIntegrationTest.java similarity index 96% rename from spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java rename to spring-boot/src/test/java/com/baeldung/validation/application/UserControllerIntegrationTest.java index 265c4ec22c..77a230ee6c 100644 --- a/spring-boot/src/test/java/com/baeldung/validation/tests/UserControllerIntegrationTest.java +++ b/spring-boot/src/test/java/com/baeldung/validation/application/UserControllerIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.validation.tests; +package com.baeldung.validation.application; import com.baeldung.validation.application.controllers.UserController; import com.baeldung.validation.application.repositories.UserRepository; From 0b9a5b3d04e74d8e615d421776cb82f14f787118 Mon Sep 17 00:00:00 2001 From: rodolforfq <31481067+rodolforfq@users.noreply.github.com> Date: Sun, 31 Mar 2019 10:48:49 -0400 Subject: [PATCH 488/496] BAEL-2806 (#6591) * BAEL-2806 Article companion code. * BAEL-2806-Rev1 Added integration tests, improved examples and fixed an error. --- .../jpa/querytypes/QueryTypesExamples.java | 69 +++++++++++++++++++ .../baeldung/jpa/querytypes/UserEntity.java | 38 ++++++++++ .../main/resources/META-INF/persistence.xml | 59 +++++++++++----- .../QueryTypesExamplesIntegrationTest.java | 65 +++++++++++++++++ .../java-jpa/src/test/resources/users.sql | 4 ++ 5 files changed, 216 insertions(+), 19 deletions(-) create mode 100644 persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/querytypes/QueryTypesExamples.java create mode 100644 persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/querytypes/UserEntity.java create mode 100644 persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/querytypes/QueryTypesExamplesIntegrationTest.java create mode 100644 persistence-modules/java-jpa/src/test/resources/users.sql diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/querytypes/QueryTypesExamples.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/querytypes/QueryTypesExamples.java new file mode 100644 index 0000000000..523fc348f9 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/querytypes/QueryTypesExamples.java @@ -0,0 +1,69 @@ +package com.baeldung.jpa.querytypes; + +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +/** + * JPA Query Types examples. All using the UserEntity class. + * + * @author Rodolfo Felipe + */ +public class QueryTypesExamples { + + EntityManagerFactory emf; + + public QueryTypesExamples() { + Map properties = new HashMap(); + properties.put("hibernate.show_sql", "true"); + properties.put("hibernate.format_sql", "true"); + emf = Persistence.createEntityManagerFactory("jpa-query-types", properties); + } + + private EntityManager getEntityManager() { + return emf.createEntityManager(); + } + + public UserEntity getUserByIdWithPlainQuery(Long id) { + Query jpqlQuery = getEntityManager().createQuery("SELECT u FROM UserEntity u WHERE u.id=:id"); + jpqlQuery.setParameter("id", id); + return (UserEntity) jpqlQuery.getSingleResult(); + } + + public UserEntity getUserByIdWithTypedQuery(Long id) { + TypedQuery typedQuery = getEntityManager().createQuery("SELECT u FROM UserEntity u WHERE u.id=:id", UserEntity.class); + typedQuery.setParameter("id", id); + return typedQuery.getSingleResult(); + } + + public UserEntity getUserByIdWithNamedQuery(Long id) { + Query namedQuery = getEntityManager().createNamedQuery("UserEntity.findByUserId"); + namedQuery.setParameter("userId", id); + return (UserEntity) namedQuery.getSingleResult(); + } + + public UserEntity getUserByIdWithNativeQuery(Long id) { + Query nativeQuery = getEntityManager().createNativeQuery("SELECT * FROM users WHERE id=:userId", UserEntity.class); + nativeQuery.setParameter("userId", id); + return (UserEntity) nativeQuery.getSingleResult(); + } + + public UserEntity getUserByIdWithCriteriaQuery(Long id) { + CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(UserEntity.class); + Root userRoot = criteriaQuery.from(UserEntity.class); + UserEntity queryResult = getEntityManager().createQuery(criteriaQuery.select(userRoot) + .where(criteriaBuilder.equal(userRoot.get("id"), id))) + .getSingleResult(); + return queryResult; + } + +} diff --git a/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/querytypes/UserEntity.java b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/querytypes/UserEntity.java new file mode 100644 index 0000000000..1d4a231b31 --- /dev/null +++ b/persistence-modules/java-jpa/src/main/java/com/baeldung/jpa/querytypes/UserEntity.java @@ -0,0 +1,38 @@ +package com.baeldung.jpa.querytypes; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.NamedQuery; +import javax.persistence.Table; + +/** + * User entity class. Used as an asset for JPA Query Types examples. + * + * @author Rodolfo Felipe + */ +@Table(name = "users") +@Entity +@NamedQuery(name = "UserEntity.findByUserId", query = "SELECT u FROM UserEntity u WHERE u.id=:userId") +public class UserEntity { + + @Id + private Long id; + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml index 6382f329c1..5422afa4a3 100644 --- a/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa/src/main/resources/META-INF/persistence.xml @@ -89,24 +89,45 @@ - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.criteria.entity.Item - true - - - - - - - - - - - - + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.criteria.entity.Item + true + + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.querytypes.UserEntity + true + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/querytypes/QueryTypesExamplesIntegrationTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/querytypes/QueryTypesExamplesIntegrationTest.java new file mode 100644 index 0000000000..4e854a464a --- /dev/null +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/querytypes/QueryTypesExamplesIntegrationTest.java @@ -0,0 +1,65 @@ +package com.baeldung.jpa.querytypes; + +import org.junit.Assert; +import org.junit.Test; + +/** + * QueryTypesExamples class integration tests. + * + * @author Rodolfo Felipe + */ +public class QueryTypesExamplesIntegrationTest { + + QueryTypesExamples userDao = new QueryTypesExamples(); + + @Test + public void givenUserId_whenCallingPlaingQueryMethod_thenReturnExpectedUser() { + UserEntity firstUser = userDao.getUserByIdWithPlainQuery(1L); + Assert.assertNotNull("User not found", firstUser); + Assert.assertEquals("User should be baeldung", "baeldung", firstUser.getName()); + UserEntity lastUser = userDao.getUserByIdWithPlainQuery(4L); + Assert.assertNotNull("User not found", lastUser); + Assert.assertEquals("User should be baeldung", "batman", lastUser.getName()); + } + + @Test + public void givenUserId_whenCallingTypedQueryMethod_thenReturnExpectedUser() { + UserEntity firstUser = userDao.getUserByIdWithTypedQuery(1L); + Assert.assertNotNull("User not found", firstUser); + Assert.assertEquals("User should be baeldung", "baeldung", firstUser.getName()); + UserEntity lastUser = userDao.getUserByIdWithTypedQuery(4L); + Assert.assertNotNull("User not found", lastUser); + Assert.assertEquals("User should be baeldung", "batman", lastUser.getName()); + } + + @Test + public void givenUserId_whenCallingNamedQueryMethod_thenReturnExpectedUser() { + UserEntity firstUser = userDao.getUserByIdWithNamedQuery(1L); + Assert.assertNotNull("User not found", firstUser); + Assert.assertEquals("User should be baeldung", "baeldung", firstUser.getName()); + UserEntity lastUser = userDao.getUserByIdWithNamedQuery(4L); + Assert.assertNotNull("User not found", lastUser); + Assert.assertEquals("User should be baeldung", "batman", lastUser.getName()); + } + + @Test + public void givenUserId_whenCallingNativeQueryMethod_thenReturnExpectedUser() { + UserEntity firstUser = userDao.getUserByIdWithNativeQuery(1L); + Assert.assertNotNull("User not found", firstUser); + Assert.assertEquals("User should be baeldung", "baeldung", firstUser.getName()); + UserEntity lastUser = userDao.getUserByIdWithNativeQuery(4L); + Assert.assertNotNull("User not found", lastUser); + Assert.assertEquals("User should be baeldung", "batman", lastUser.getName()); + } + + @Test + public void givenUserId_whenCallingCriteriaApiMethod_thenReturnExpectedUser() { + UserEntity firstUser = userDao.getUserByIdWithCriteriaQuery(1L); + Assert.assertNotNull("User not found", firstUser); + Assert.assertEquals("User should be baeldung", "baeldung", firstUser.getName()); + UserEntity lastUser = userDao.getUserByIdWithCriteriaQuery(4L); + Assert.assertNotNull("User not found", lastUser); + Assert.assertEquals("User should be baeldung", "batman", lastUser.getName()); + } + +} diff --git a/persistence-modules/java-jpa/src/test/resources/users.sql b/persistence-modules/java-jpa/src/test/resources/users.sql new file mode 100644 index 0000000000..227022e5df --- /dev/null +++ b/persistence-modules/java-jpa/src/test/resources/users.sql @@ -0,0 +1,4 @@ +INSERT INTO users(id,name) VALUES(1,'baeldung'); +INSERT INTO users(id,name) VALUES(2,'john doe'); +INSERT INTO users(id,name) VALUES(3,'jane doe'); +INSERT INTO users(id,name) VALUES(4,'batman'); From 183dfdf1abdfd4677edd03fb36452dd6f115cc87 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 31 Mar 2019 21:23:49 +0530 Subject: [PATCH 489/496] [BAEL-8938] - Added spring jdbc article in spring-all module --- spring-all/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/spring-all/README.md b/spring-all/README.md index 82d876768e..a111d2e542 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -33,3 +33,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring @Primary Annotation](http://www.baeldung.com/spring-primary) - [Spring Events](https://www.baeldung.com/spring-events) - [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations) +- [Spring JDBC](https://www.baeldung.com/spring-jdbc-jdbctemplate) From 27699842f6a4f37c113ef6dac17067c141efdbb0 Mon Sep 17 00:00:00 2001 From: amit2103 Date: Sun, 31 Mar 2019 23:07:34 +0530 Subject: [PATCH 490/496] [BAEL-13322] - Removed noexception module : Code already present in libraries module --- noexception/pom.xml | 27 -------- .../noexception/CustomExceptionHandler.java | 24 ------- noexception/src/main/resources/logback.xml | 13 ---- .../noexception/NoExceptionUnitTest.java | 63 ------------------- pom.xml | 2 - 5 files changed, 129 deletions(-) delete mode 100644 noexception/pom.xml delete mode 100644 noexception/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java delete mode 100644 noexception/src/main/resources/logback.xml delete mode 100644 noexception/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java diff --git a/noexception/pom.xml b/noexception/pom.xml deleted file mode 100644 index f632f1e3a9..0000000000 --- a/noexception/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - 4.0.0 - com.baeldung - noexception - 1.0 - noexception - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - com.machinezoo.noexception - noexception - ${noexception.version} - - - - - 1.1.0 - - - diff --git a/noexception/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java b/noexception/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java deleted file mode 100644 index 59e13efaa0..0000000000 --- a/noexception/src/main/java/com/baeldung/noexception/CustomExceptionHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.noexception; - -import com.machinezoo.noexception.ExceptionHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CustomExceptionHandler extends ExceptionHandler { - - private Logger logger = LoggerFactory.getLogger(CustomExceptionHandler.class); - - @Override - public boolean handle(Throwable throwable) { - - if (throwable.getClass() - .isAssignableFrom(RuntimeException.class) - || throwable.getClass() - .isAssignableFrom(Error.class)) { - return false; - } else { - logger.error("Caught Exception ", throwable); - return true; - } - } -} diff --git a/noexception/src/main/resources/logback.xml b/noexception/src/main/resources/logback.xml deleted file mode 100644 index 7d900d8ea8..0000000000 --- a/noexception/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/noexception/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java b/noexception/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java deleted file mode 100644 index 690ea43520..0000000000 --- a/noexception/src/test/java/com/baeldung/noexception/NoExceptionUnitTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.baeldung.noexception; - -import com.machinezoo.noexception.Exceptions; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class NoExceptionUnitTest { - - private static Logger logger = LoggerFactory.getLogger(NoExceptionUnitTest.class); - - @Test - public void whenStdExceptionHandling_thenCatchAndLog() { - try { - System.out.println("Result is " + Integer.parseInt("foobar")); - } catch (Throwable exception) { - logger.error("Caught exception:", exception); - } - } - - @Test - public void whenDefaultNoException_thenCatchAndLog() { - - Exceptions.log().run(() -> System.out.println("Result is " + Integer.parseInt("foobar"))); - } - - @Test - public void givenLogger_whenDefaultNoException_thenCatchAndLogWithClassName() { - System.out.println("Result is " + Exceptions.log(logger).get(() -> +Integer.parseInt("foobar")).orElse(-1)); - } - - @Test - public void givenLoggerAndMessage_whenDefaultNoException_thenCatchAndLogWithClassNameAndMessage() { - System.out.println("Result is " + Exceptions.log(logger, "Something went wrong:").get(() -> +Integer.parseInt("foobar")).orElse(-1)); - } - - @Test - public void givenDefaultValue_whenDefaultNoException_thenCatchAndLogPrintDefault() { - System.out.println("Result is " + Exceptions.log(logger, "Something went wrong:").get(() -> +Integer.parseInt("foobar")).orElse(-1)); - } - - @Test(expected = Error.class) - public void givenCustomHandler_whenError_thenRethrowError() { - CustomExceptionHandler customExceptionHandler = new CustomExceptionHandler(); - customExceptionHandler.run(() -> throwError()); - } - - @Test - public void givenCustomHandler_whenException_thenCatchAndLog() { - CustomExceptionHandler customExceptionHandler = new CustomExceptionHandler(); - customExceptionHandler.run(() -> throwException()); - } - - private static void throwError() { - throw new Error("This is very bad."); - } - - private static void throwException() { - String testString = "foo"; - testString.charAt(5); - } - -} diff --git a/pom.xml b/pom.xml index eaaf90899f..a832d6156f 100644 --- a/pom.xml +++ b/pom.xml @@ -504,7 +504,6 @@ mustache mybatis - noexception optaplanner orika @@ -1149,7 +1148,6 @@ mustache mybatis - noexception optaplanner orika From 33e7f0d8e3354499ebec908a96309c108055fad7 Mon Sep 17 00:00:00 2001 From: Kumar Chandrakant Date: Mon, 1 Apr 2019 01:21:01 +0530 Subject: [PATCH 491/496] Adding code for the tutorial tracked under BAEL-2488 (#6598) --- .../config/WebSocketMessageBrokerConfig.java | 67 +++++++++++++++++++ .../controllers/RestAPIController.java | 17 +++++ .../controllers/WebSocketController.java | 20 ++++++ .../springsockets/models/Greeting.java | 18 +++++ .../springsockets/models/Message.java | 22 ++++++ .../src/main/resources/static/rest.html | 39 +++++++++++ .../src/main/resources/static/rest.js | 21 ++++++ .../src/main/resources/static/ws.html | 39 +++++++++++ .../src/main/resources/static/ws.js | 26 +++++++ 9 files changed, 269 insertions(+) create mode 100644 spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/config/WebSocketMessageBrokerConfig.java create mode 100644 spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/controllers/RestAPIController.java create mode 100644 spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/controllers/WebSocketController.java create mode 100644 spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/models/Greeting.java create mode 100644 spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/models/Message.java create mode 100644 spring-security-mvc-socket/src/main/resources/static/rest.html create mode 100644 spring-security-mvc-socket/src/main/resources/static/rest.js create mode 100644 spring-security-mvc-socket/src/main/resources/static/ws.html create mode 100644 spring-security-mvc-socket/src/main/resources/static/ws.js diff --git a/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/config/WebSocketMessageBrokerConfig.java b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/config/WebSocketMessageBrokerConfig.java new file mode 100644 index 0000000000..f1fb6549ed --- /dev/null +++ b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/config/WebSocketMessageBrokerConfig.java @@ -0,0 +1,67 @@ +package com.baeldung.springsockets.config; + +import java.util.List; + +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.converter.MessageConverter; +import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; +import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler; +import org.springframework.messaging.simp.config.ChannelRegistration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration; + +@Configuration +@EnableWebSocketMessageBroker +public class WebSocketMessageBrokerConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/ws"); + } + + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { + config.setApplicationDestinationPrefixes("/app"); + config.enableSimpleBroker("/topic"); + } + + @Override + public void configureWebSocketTransport(WebSocketTransportRegistration registry) { + // TODO Auto-generated method stub + + } + + @Override + public void configureClientInboundChannel(ChannelRegistration registration) { + // TODO Auto-generated method stub + + } + + @Override + public void configureClientOutboundChannel(ChannelRegistration registration) { + // TODO Auto-generated method stub + + } + + @Override + public void addArgumentResolvers(List argumentResolvers) { + // TODO Auto-generated method stub + + } + + @Override + public void addReturnValueHandlers(List returnValueHandlers) { + // TODO Auto-generated method stub + + } + + @Override + public boolean configureMessageConverters(List messageConverters) { + // TODO Auto-generated method stub + return false; + } + +} \ No newline at end of file diff --git a/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/controllers/RestAPIController.java b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/controllers/RestAPIController.java new file mode 100644 index 0000000000..a8d3d5ffae --- /dev/null +++ b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/controllers/RestAPIController.java @@ -0,0 +1,17 @@ +package com.baeldung.springsockets.controllers; + +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; + +@RestController +@RequestMapping(path = "/rest") +public class RestAPIController { + + @GetMapping(path = "/{name}", produces = "application/json") + public String getGreeting(@PathVariable("name") String name) { + return "{\"greeting\" : \"Hello, " + name + "!\"}"; + } + +} diff --git a/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/controllers/WebSocketController.java b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/controllers/WebSocketController.java new file mode 100644 index 0000000000..26a67e4236 --- /dev/null +++ b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/controllers/WebSocketController.java @@ -0,0 +1,20 @@ +package com.baeldung.springsockets.controllers; + +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.stereotype.Controller; +import org.springframework.web.util.HtmlUtils; + +import com.baeldung.springsockets.models.Greeting; +import com.baeldung.springsockets.models.Message; + +@Controller +public class WebSocketController { + + @MessageMapping("/hello") + @SendTo("/topic/greetings") + public Greeting greeting(Message message) throws Exception { + return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"); + } + +} \ No newline at end of file diff --git a/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/models/Greeting.java b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/models/Greeting.java new file mode 100644 index 0000000000..b6122ac1e7 --- /dev/null +++ b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/models/Greeting.java @@ -0,0 +1,18 @@ +package com.baeldung.springsockets.models; + +public class Greeting { + + private String content; + + public Greeting() { + } + + public Greeting(String content) { + this.content = content; + } + + public String getContent() { + return content; + } + +} diff --git a/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/models/Message.java b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/models/Message.java new file mode 100644 index 0000000000..4dd002606a --- /dev/null +++ b/spring-security-mvc-socket/src/main/java/com/baeldung/springsockets/models/Message.java @@ -0,0 +1,22 @@ +package com.baeldung.springsockets.models; + +public class Message { + + private String name; + + public Message() { + } + + public Message(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/spring-security-mvc-socket/src/main/resources/static/rest.html b/spring-security-mvc-socket/src/main/resources/static/rest.html new file mode 100644 index 0000000000..476d053eea --- /dev/null +++ b/spring-security-mvc-socket/src/main/resources/static/rest.html @@ -0,0 +1,39 @@ + + + + Demo for RESTful Service for Comparison to WebSocket + + + + + + + +
+
+
+
+
+ + +
+ +
+
+
+
+
+ + + + + + + + +
Greetings
+
+
+
+ + \ No newline at end of file diff --git a/spring-security-mvc-socket/src/main/resources/static/rest.js b/spring-security-mvc-socket/src/main/resources/static/rest.js new file mode 100644 index 0000000000..403cc63585 --- /dev/null +++ b/spring-security-mvc-socket/src/main/resources/static/rest.js @@ -0,0 +1,21 @@ +var request = new XMLHttpRequest() + +function sendName() { + request.open('GET', 'http://localhost:8080/rest/'+$("#name").val(), true) + request.onload = function () { + var data = JSON.parse(this.response) + showGreeting(data.greeting) + } + request.send() +} + +function showGreeting(message) { + $("#greetings").append("" + message + ""); +} + +$(function () { + $("form").on('submit', function (e) { + e.preventDefault(); + }); + $( "#send" ).click(function() { sendName(); }); +}); \ No newline at end of file diff --git a/spring-security-mvc-socket/src/main/resources/static/ws.html b/spring-security-mvc-socket/src/main/resources/static/ws.html new file mode 100644 index 0000000000..638b8c0857 --- /dev/null +++ b/spring-security-mvc-socket/src/main/resources/static/ws.html @@ -0,0 +1,39 @@ + + + + Demo for WebSocket for Comparison to RESTful Service + + + + + + + +
+
+
+
+
+ + +
+ +
+
+
+
+
+ + + + + + + + +
Greetings
+
+
+
+ + \ No newline at end of file diff --git a/spring-security-mvc-socket/src/main/resources/static/ws.js b/spring-security-mvc-socket/src/main/resources/static/ws.js new file mode 100644 index 0000000000..538faf4e61 --- /dev/null +++ b/spring-security-mvc-socket/src/main/resources/static/ws.js @@ -0,0 +1,26 @@ +var stompClient = null; + +function connect() { + stompClient = Stomp.client('ws://localhost:8080/ws'); + stompClient.connect({}, function (frame) { + stompClient.subscribe('/topic/greetings', function (response) { + showGreeting(JSON.parse(response.body).content); + }); + }); +} + +function sendName() { + stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()})); +} + +function showGreeting(message) { + $("#greetings").append("" + message + ""); +} + +$(function () { + connect(); + $("form").on('submit', function (e) { + e.preventDefault(); + }); + $( "#send" ).click(function() { sendName(); }); +}); \ No newline at end of file From 295b78661ae6af2b2e1ec2daf2f5db3b3422b3cc Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 31 Mar 2019 22:08:40 +0200 Subject: [PATCH 492/496] BAEL-1931 Kerberos integration in Java (#6559) * BAEL-1931 kerberos integration in java * add javadoc to manual test * use list in mini kdc builder, constructor injection in service * remove unused constant --- spring-security-sso/pom.xml | 5 +- .../spring-security-sso-kerberos/.gitignore | 2 + .../spring-security-sso-kerberos/pom.xml | 94 ++++++++++++++++ .../kerberos/client/KerberosClientApp.java | 20 ++++ .../java/kerberos/client/SampleService.java | 26 +++++ .../kerberos/client/config/AppConfig.java | 10 ++ .../client/config/KerberosConfig.java | 22 ++++ .../java/kerberos/kdc/KerberosMiniKdc.java | 35 ++++++ .../kerberos/kdc/MiniKdcConfigBuilder.java | 64 +++++++++++ .../kerberos/server/KerberizedServerApp.java | 22 ++++ .../kerberos/server/config/MvcConfig.java | 18 +++ .../server/config/WebSecurityConfig.java | 103 ++++++++++++++++++ .../server/controller/SampleController.java | 15 +++ .../service/DummyUserDetailsService.java | 16 +++ .../src/main/resources/application.properties | 6 + .../src/main/resources/minikdc-krb5.conf | 25 +++++ .../src/main/resources/minikdc.ldiff | 47 ++++++++ .../src/main/resources/templates/hello.html | 10 ++ .../src/main/resources/templates/home.html | 10 ++ .../src/main/resources/templates/login.html | 20 ++++ .../client/SampleServiceManualTest.java | 43 ++++++++ 21 files changed, 612 insertions(+), 1 deletion(-) create mode 100644 spring-security-sso/spring-security-sso-kerberos/.gitignore create mode 100644 spring-security-sso/spring-security-sso-kerberos/pom.xml create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/KerberosClientApp.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleService.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/config/AppConfig.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/config/KerberosConfig.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/kdc/KerberosMiniKdc.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/kdc/MiniKdcConfigBuilder.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/KerberizedServerApp.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/config/MvcConfig.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/config/WebSecurityConfig.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/controller/SampleController.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/service/DummyUserDetailsService.java create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/resources/application.properties create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/resources/minikdc-krb5.conf create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/resources/minikdc.ldiff create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/hello.html create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/home.html create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/login.html create mode 100644 spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleServiceManualTest.java diff --git a/spring-security-sso/pom.xml b/spring-security-sso/pom.xml index 707f516da2..ed8ad87a62 100644 --- a/spring-security-sso/pom.xml +++ b/spring-security-sso/pom.xml @@ -18,12 +18,15 @@ spring-security-sso-auth-server spring-security-sso-ui spring-security-sso-ui-2 + spring-security-sso-kerberos 3.1.0 2.3.3.RELEASE - 2.1.1.RELEASE + 2.1.1.RELEASE + 1.0.1.RELEASE + 2.0.0-M2 diff --git a/spring-security-sso/spring-security-sso-kerberos/.gitignore b/spring-security-sso/spring-security-sso-kerberos/.gitignore new file mode 100644 index 0000000000..a90740bb66 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/.gitignore @@ -0,0 +1,2 @@ +krb-test-workdir/ +/bin/ diff --git a/spring-security-sso/spring-security-sso-kerberos/pom.xml b/spring-security-sso/spring-security-sso-kerberos/pom.xml new file mode 100644 index 0000000000..5fb435a9b9 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/pom.xml @@ -0,0 +1,94 @@ + + + 4.0.0 + spring-security-sso-kerberos + + + org.baeldung + spring-security-sso + 1.0.0-SNAPSHOT + + + + + + ${basedir}/src/main/resources + true + + **/* + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + + @ + + false + + + + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security.kerberos + spring-security-kerberos-web + ${spring-security-kerberos.version} + + + org.springframework.security.kerberos + spring-security-kerberos-client + ${spring-security-kerberos.version} + + + org.apache.directory.jdbm + apacheds-jdbm1 + ${apacheds-jdbm1.version} + + + org.springframework.security.kerberos + spring-security-kerberos-test + + + org.apache.directory.jdbm + apacheds-jdbm1 + + + org.slf4j + slf4j-log4j12 + + + ${spring-security-kerberos.version} + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + \ No newline at end of file diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/KerberosClientApp.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/KerberosClientApp.java new file mode 100644 index 0000000000..a353961854 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/KerberosClientApp.java @@ -0,0 +1,20 @@ +package kerberos.client; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import java.nio.file.Paths; + +@SpringBootApplication +class KerberosClientApp { + + static { + System.setProperty("java.security.krb5.conf", + Paths.get(".\\krb-test-workdir\\krb5.conf").normalize().toAbsolutePath().toString()); + System.setProperty("sun.security.krb5.debug", "true"); + } + + public static void main(String[] args) { + SpringApplication.run(KerberosClientApp.class, args); + } +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleService.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleService.java new file mode 100644 index 0000000000..4145cf0c1a --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleService.java @@ -0,0 +1,26 @@ +package kerberos.client; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Service +class SampleService { + + @Value("${app.access-url}") + private String endpoint; + + private RestTemplate restTemplate; + + public SampleService(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + void setRestTemplate(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + String getData() { + return restTemplate.getForObject(endpoint, String.class); + } +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/config/AppConfig.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/config/AppConfig.java new file mode 100644 index 0000000000..5248f648f9 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/config/AppConfig.java @@ -0,0 +1,10 @@ +package kerberos.client.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +@Configuration +@Import(KerberosConfig.class) +class AppConfig { + +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/config/KerberosConfig.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/config/KerberosConfig.java new file mode 100644 index 0000000000..9ab775e95d --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/config/KerberosConfig.java @@ -0,0 +1,22 @@ +package kerberos.client.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.kerberos.client.KerberosRestTemplate; +import org.springframework.web.client.RestTemplate; + +@Configuration +class KerberosConfig { + + @Value("${app.user-principal}") + private String principal; + + @Value("${app.keytab-location}") + private String keytabLocation; + + @Bean + public RestTemplate restTemplate() { + return new KerberosRestTemplate(keytabLocation, principal); + } +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/kdc/KerberosMiniKdc.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/kdc/KerberosMiniKdc.java new file mode 100644 index 0000000000..60cf3ca1c2 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/kdc/KerberosMiniKdc.java @@ -0,0 +1,35 @@ +package kerberos.kdc; + +import org.apache.commons.io.FileUtils; +import org.springframework.security.kerberos.test.MiniKdc; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +class KerberosMiniKdc { + + private static final String KRB_WORK_DIR = ".\\spring-security-sso\\spring-security-sso-kerberos\\krb-test-workdir"; + + public static void main(String[] args) throws Exception { + + String[] config = MiniKdcConfigBuilder.builder() + .workDir(prepareWorkDir()) + .confDir("minikdc-krb5.conf") + .keytabName("example.keytab") + .principals("client/localhost", "HTTP/localhost") + .build(); + + MiniKdc.main(config); + } + + private static String prepareWorkDir() throws IOException { + Path dir = Paths.get(KRB_WORK_DIR); + File directory = dir.normalize().toFile(); + + FileUtils.deleteQuietly(directory); + FileUtils.forceMkdir(directory); + return dir.toString(); + } +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/kdc/MiniKdcConfigBuilder.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/kdc/MiniKdcConfigBuilder.java new file mode 100644 index 0000000000..a9dd21a175 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/kdc/MiniKdcConfigBuilder.java @@ -0,0 +1,64 @@ +package kerberos.kdc; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Objects; + +class MiniKdcConfigBuilder { + + private String workDir; + private String confDir; + private String keytabName; + private Collection principals; + + private MiniKdcConfigBuilder() { + // desired + } + + static MiniKdcConfigBuilder builder() { + return new MiniKdcConfigBuilder(); + } + + MiniKdcConfigBuilder workDir(String workDir) { + this.workDir = workDir; + return this; + } + + MiniKdcConfigBuilder confDir(String cfg) { + try { + URL resource = Thread.currentThread().getContextClassLoader().getResource(cfg); + URI uri = Objects.requireNonNull(resource).toURI(); + this.confDir = Paths.get(uri).toString(); + } catch (URISyntaxException cause) { + throw new IllegalStateException("Could not resolve path for: " + cfg, cause); + } + return this; + } + + MiniKdcConfigBuilder keytabName(String keytabName) { + this.keytabName = Paths.get(workDir).resolve(keytabName).toString(); + return this; + } + + MiniKdcConfigBuilder principals(String... principals) { + this.principals = Arrays.asList(principals); + return this; + } + + String[] build() { + + Collection miniKdcConfig = new ArrayList<>(); + + miniKdcConfig.add(workDir); + miniKdcConfig.add(confDir); + miniKdcConfig.add(keytabName); + miniKdcConfig.addAll(principals); + + return miniKdcConfig.toArray(new String[0]); + } +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/KerberizedServerApp.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/KerberizedServerApp.java new file mode 100644 index 0000000000..8286013605 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/KerberizedServerApp.java @@ -0,0 +1,22 @@ +package kerberos.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import java.nio.file.Paths; + +@SpringBootApplication +public class KerberizedServerApp { + + static { + System.setProperty("java.security.krb5.conf", + Paths.get(".\\spring-security-sso\\spring-security-sso-kerberos\\krb-test-workdir\\krb5.conf") + .normalize().toAbsolutePath().toString()); + System.setProperty("sun.security.krb5.debug", "true"); + } + + public static void main(String[] args) { + + SpringApplication.run(KerberizedServerApp.class, args); + } +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/config/MvcConfig.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/config/MvcConfig.java new file mode 100644 index 0000000000..3ad07e407b --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/config/MvcConfig.java @@ -0,0 +1,18 @@ +package kerberos.server.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +class MvcConfig extends WebMvcConfigurerAdapter { + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/home").setViewName("home"); + registry.addViewController("/").setViewName("home"); + registry.addViewController("/hello").setViewName("hello"); + registry.addViewController("/login").setViewName("login"); + } + +} \ No newline at end of file diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/config/WebSecurityConfig.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/config/WebSecurityConfig.java new file mode 100644 index 0000000000..5d241c5823 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/config/WebSecurityConfig.java @@ -0,0 +1,103 @@ +package kerberos.server.config; + +import kerberos.server.service.DummyUserDetailsService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.FileSystemResource; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider; +import org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider; +import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient; +import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator; +import org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter; +import org.springframework.security.kerberos.web.authentication.SpnegoEntryPoint; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +@Configuration +@EnableWebSecurity +class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + @Value("${app.service-principal}") + private String servicePrincipal; + + @Value("${app.keytab-location}") + private String keytabLocation; + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.exceptionHandling() + .authenticationEntryPoint(spnegoEntryPoint()) + .and() + .authorizeRequests().antMatchers("/", "/home").permitAll() + .anyRequest().authenticated() + .and() + .formLogin().loginPage("/login").permitAll() + .and() + .logout().permitAll() + .and() + .addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManagerBean()), + BasicAuthenticationFilter.class); + } + + @Bean + public AuthenticationManager anAuthenticationManager() throws Exception { + return authenticationManager(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.authenticationProvider(kerberosAuthenticationProvider()) + .authenticationProvider(kerberosServiceAuthenticationProvider()); + } + + @Bean + public KerberosAuthenticationProvider kerberosAuthenticationProvider() { + KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider(); + SunJaasKerberosClient client = new SunJaasKerberosClient(); + client.setDebug(true); + provider.setKerberosClient(client); + provider.setUserDetailsService(dummyUserDetailsService()); + return provider; + } + + @Bean + public SpnegoEntryPoint spnegoEntryPoint() { + return new SpnegoEntryPoint("/login"); + } + + @Bean + public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter( + AuthenticationManager authenticationManager) { + SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter(); + filter.setAuthenticationManager(authenticationManager); + return filter; + } + + @Bean + public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() { + KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider(); + provider.setTicketValidator(sunJaasKerberosTicketValidator()); + provider.setUserDetailsService(dummyUserDetailsService()); + return provider; + } + + @Bean + public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() { + SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator(); + ticketValidator.setServicePrincipal(servicePrincipal); + ticketValidator.setKeyTabLocation(new FileSystemResource(keytabLocation)); + ticketValidator.setDebug(true); + return ticketValidator; + } + + @Bean + public DummyUserDetailsService dummyUserDetailsService() { + return new DummyUserDetailsService(); + } + +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/controller/SampleController.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/controller/SampleController.java new file mode 100644 index 0000000000..b1d3e6fb90 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/controller/SampleController.java @@ -0,0 +1,15 @@ +package kerberos.server.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/endpoint") +class SampleController { + + @GetMapping + String getIt() { + return "data from kerberized server"; + } +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/service/DummyUserDetailsService.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/service/DummyUserDetailsService.java new file mode 100644 index 0000000000..06942d8dc7 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/server/service/DummyUserDetailsService.java @@ -0,0 +1,16 @@ +package kerberos.server.service; + +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +public class DummyUserDetailsService implements UserDetailsService { + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + return new User(username, "notUsed", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_USER")); + } + +} diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/resources/application.properties b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/application.properties new file mode 100644 index 0000000000..b36575460c --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/application.properties @@ -0,0 +1,6 @@ +# make sure the same data is configured in KerberosMiniKdc +# otherwise configuration/communication error will occur +app.service-principal=HTTP/localhost +app.user-principal=client/localhost +app.keytab-location=@project.basedir@\\krb-test-workdir\\example.keytab +app.access-url=http://localhost:8080/endpoint diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/resources/minikdc-krb5.conf b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/minikdc-krb5.conf new file mode 100644 index 0000000000..ea1e9d1ceb --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/minikdc-krb5.conf @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +[libdefaults] +default_realm = {0} +udp_preference_limit = 1 + +[realms] +{0} = '{' + kdc = {1}:{2} + '}' \ No newline at end of file diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/resources/minikdc.ldiff b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/minikdc.ldiff new file mode 100644 index 0000000000..603ccb5fd9 --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/minikdc.ldiff @@ -0,0 +1,47 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +dn: ou=users,dc=${0},dc=${1} +objectClass: organizationalUnit +objectClass: top +ou: users + +dn: uid=krbtgt,ou=users,dc=${0},dc=${1} +objectClass: top +objectClass: person +objectClass: inetOrgPerson +objectClass: krb5principal +objectClass: krb5kdcentry +cn: KDC Service +sn: Service +uid: krbtgt +userPassword: secret +krb5PrincipalName: krbtgt/${2}.${3}@${2}.${3} +krb5KeyVersionNumber: 0 + +dn: uid=ldap,ou=users,dc=${0},dc=${1} +objectClass: top +objectClass: person +objectClass: inetOrgPerson +objectClass: krb5principal +objectClass: krb5kdcentry +cn: LDAP +sn: Service +uid: ldap +userPassword: secret +krb5PrincipalName: ldap/${4}@${2}.${3} +krb5KeyVersionNumber: 0 \ No newline at end of file diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/hello.html b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/hello.html new file mode 100644 index 0000000000..71a756386b --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/hello.html @@ -0,0 +1,10 @@ + + + + Spring Security Kerberos Example + + +

Hello [[${#httpServletRequest.remoteUser}]]!

+ + diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/home.html b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/home.html new file mode 100644 index 0000000000..d8e37e443d --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/home.html @@ -0,0 +1,10 @@ + + + + Spring Security Kerberos Example + + +

Welcome!

+

Click here to see a greeting.

+ + diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/login.html b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/login.html new file mode 100644 index 0000000000..b96252192f --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/main/resources/templates/login.html @@ -0,0 +1,20 @@ + + + + Spring Security Kerberos Example + + +
+ Invalid username and password. +
+
+ You have been logged out. +
+
+
+
+
+
+ + diff --git a/spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleServiceManualTest.java b/spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleServiceManualTest.java new file mode 100644 index 0000000000..d0d9f0ae4b --- /dev/null +++ b/spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleServiceManualTest.java @@ -0,0 +1,43 @@ +package kerberos.client; + +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * Procedure to run this manual test: + *
    + *
  1. Start {@code KerberosMiniKdc}
  2. + *
  3. Start {@code KerberizedServerApp}
  4. + *
  5. Run the test
  6. + *
+ */ +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@FixMethodOrder +public class SampleServiceManualTest { + + @Autowired + private SampleService sampleService; + + @Test + public void a_givenKerberizedRestTemplate_whenServiceCall_thenSuccess() { + assertNotNull(sampleService); + assertEquals("data from kerberized server", sampleService.getData()); + } + + @Test + public void b_givenRestTemplate_whenServiceCall_thenFail() { + sampleService.setRestTemplate(new RestTemplate()); + assertThrows(RestClientException.class, sampleService::getData); + } +} \ No newline at end of file From 3465c347d50fbc0128815df61dbeae6ca977b787 Mon Sep 17 00:00:00 2001 From: Shubhra Srivastava Date: Mon, 1 Apr 2019 03:17:52 +0530 Subject: [PATCH 493/496] Bael 2826 case insensitive spring data jpa (#6625) * BAEL-2826: Case Insensitive Comparison Spring data jpa * BAEL-2826: Fixing imports --- .../passenger/PassengerRepository.java | 3 ++ .../PassengerRepositoryIntegrationTest.java | 53 ++++++++++++------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepository.java index 6ae6afb403..b2d145899e 100644 --- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepository.java +++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepository.java @@ -14,4 +14,7 @@ interface PassengerRepository extends JpaRepository, CustomPass List findByLastNameOrderBySeatNumberAsc(String lastName); List findByLastName(String lastName, Sort sort); + + List findByFirstNameIgnoreCase(String firstName); + } diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java index 8cd19cec03..2b303604b6 100644 --- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/passenger/PassengerRepositoryIntegrationTest.java @@ -1,17 +1,5 @@ package com.baeldung.passenger; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.core.IsNot.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.List; -import java.util.Optional; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -24,6 +12,17 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.test.context.junit4.SpringRunner; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; +import java.util.Optional; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + @DataJpaTest @RunWith(SpringRunner.class) public class PassengerRepositoryIntegrationTest { @@ -152,18 +151,36 @@ public class PassengerRepositoryIntegrationTest { Passenger fred = Passenger.from("Fred", "Bloggs", 22); Passenger siya = Passenger.from("Siya", "Kolisi", 85); Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); - + ExampleMatcher ignoringExampleMatcher = ExampleMatcher.matchingAny().withMatcher("lastName", - ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase()).withIgnorePaths("firstName", "seatNumber"); - + ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase()).withIgnorePaths("firstName", "seatNumber"); + Example example = Example.of(Passenger.from(null, "b", null), - ignoringExampleMatcher); - + ignoringExampleMatcher); + List passengers = repository.findAll(example); - + assertThat(passengers, contains(fred, ricki)); assertThat(passengers, not(contains(jill))); assertThat(passengers, not(contains(eve))); assertThat(passengers, not(contains(siya))); } + + @Test + public void givenPassengers_whenMatchingIgnoreCase_thenExpectedReturned() { + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + + List passengers = repository.findByFirstNameIgnoreCase("FRED"); + + assertThat(passengers, contains(fred)); + assertThat(passengers, not(contains(eve))); + assertThat(passengers, not(contains(siya))); + assertThat(passengers, not(contains(jill))); + assertThat(passengers, not(contains(ricki))); + + } } From 7b51ca1dce1914844da4d7bfb65c456a0798519f Mon Sep 17 00:00:00 2001 From: jarpz Date: Sun, 31 Mar 2019 16:53:43 -0500 Subject: [PATCH 494/496] feat(like-expressions): add Song + SongRepository with integration tests (#6633) --- .../main/java/com/baeldung/entity/Song.java | 75 +++++++++++++++++++ .../baeldung/repository/SongRepository.java | 21 ++++++ .../SongRepositoryIntegrationTest.java | 57 ++++++++++++++ .../src/test/resources/test-song-data.sql | 8 ++ 4 files changed, 161 insertions(+) create mode 100644 persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Song.java create mode 100644 persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/SongRepository.java create mode 100644 persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/SongRepositoryIntegrationTest.java create mode 100644 persistence-modules/spring-data-jpa-2/src/test/resources/test-song-data.sql diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Song.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Song.java new file mode 100644 index 0000000000..395527c1eb --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Song.java @@ -0,0 +1,75 @@ +package com.baeldung.entity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import java.time.LocalDateTime; + +@Entity +public class Song { + + @Id private long id; + private String name; + @Column(name = "length_in_seconds") + private int lengthInSeconds; + private String compositor; + private String singer; + private LocalDateTime released; + private String genre; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getLengthInSeconds() { + return lengthInSeconds; + } + + public void setLengthInSeconds(int lengthInSeconds) { + this.lengthInSeconds = lengthInSeconds; + } + + public String getCompositor() { + return compositor; + } + + public void setCompositor(String compositor) { + this.compositor = compositor; + } + + public String getSinger() { + return singer; + } + + public void setSinger(String singer) { + this.singer = singer; + } + + public LocalDateTime getReleased() { + return released; + } + + public void setReleased(LocalDateTime released) { + this.released = released; + } + + public String getGenre() { + return genre; + } + + public void setGenre(String genre) { + this.genre = genre; + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/SongRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/SongRepository.java new file mode 100644 index 0000000000..ad887fe680 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/SongRepository.java @@ -0,0 +1,21 @@ +package com.baeldung.repository; + +import com.baeldung.entity.Song; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface SongRepository extends JpaRepository { + + List findByNameLike(String name); + + List findByNameNotLike(String name); + + List findByNameStartingWith(String startingWith); + + List findByNameEndingWith(String endingWith); + + List findBySingerContaining(String singer); +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/SongRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/SongRepositoryIntegrationTest.java new file mode 100644 index 0000000000..c3d0636881 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/SongRepositoryIntegrationTest.java @@ -0,0 +1,57 @@ +package com.baeldung.repository; + +import com.baeldung.entity.Song; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest +@Sql(scripts = { "/test-song-data.sql" }) +public class SongRepositoryIntegrationTest { + + @Autowired private SongRepository songRepository; + + @Transactional + @Test + public void givenSong_WhenFindLikeByName_ThenShouldReturnOne() { + List songs = songRepository.findByNameLike("Despacito"); + assertEquals(1, songs.size()); + } + + @Transactional + @Test + public void givenSong_WhenFindByNameNotLike_thenShouldReturn3Songs() { + List songs = songRepository.findByNameNotLike("Despacito"); + assertEquals(5, songs.size()); + } + + @Transactional + @Test + public void givenSong_WhenFindByNameStartingWith_thenShouldReturn2Songs() { + List songs = songRepository.findByNameStartingWith("Co"); + assertEquals(2, songs.size()); + } + + @Transactional + @Test + public void givenSong_WhenFindByNameEndingWith_thenShouldReturn2Songs() { + List songs = songRepository.findByNameEndingWith("Life"); + assertEquals(2, songs.size()); + } + + @Transactional + @Test + public void givenSong_WhenFindBySingerContaining_thenShouldReturn2Songs() { + List songs = songRepository.findBySingerContaining("Luis"); + assertEquals(2, songs.size()); + } +} diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/test-song-data.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/test-song-data.sql new file mode 100644 index 0000000000..5a2b1a5555 --- /dev/null +++ b/persistence-modules/spring-data-jpa-2/src/test/resources/test-song-data.sql @@ -0,0 +1,8 @@ +INSERT INTO song(id,name,length_in_seconds,compositor,singer,released,genre) +VALUES +(1,'Despacito',209,'Luis Fonsi','Luis Fonsi, Daddy Yankee','2017-01-12','Reggaeton'), +(2,'Con calma',188,'Daddy Yankee','Daddy Yankee','2019-01-24','Reggaeton'), +(3,'It''s My Life',205,'Bon Jovi','Jon Bon Jovi','2000-05-23','Pop'), +(4,'Live is Life',242,'Opus','Opus','1985-01-01','Reggae'), +(5,'Countdown to Extinction',249,'Megadeth','Megadeth','1992-07-14','Heavy Metal'), +(6, 'Si nos dejan',139,'Luis Miguel','Luis Miguel','1995-10-17','Bolero'); \ No newline at end of file From aaf80f0d2d671ace176ad870a30e6089953996fb Mon Sep 17 00:00:00 2001 From: eric-martin Date: Sun, 31 Mar 2019 21:37:40 -0500 Subject: [PATCH 495/496] Issue-6604: Upgrade spring cloud to Edgware.SR5 --- spring-cloud/spring-cloud-bootstrap/discovery/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml b/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml index 735d3745d7..09bea4864a 100644 --- a/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml @@ -50,6 +50,6 @@ - Brixton.SR7 + Edgware.SR5 \ No newline at end of file From 4932689c32d05fca145091b5ad2c67ec2eaf95e5 Mon Sep 17 00:00:00 2001 From: letcodespeak <44544000+letcodespeak@users.noreply.github.com> Date: Mon, 1 Apr 2019 14:00:07 +1100 Subject: [PATCH 496/496] BAEL-2569 EnvironmentPostProcessor in Spring Boot (#6608) * BAEL-2569 : EnvironmentPostProcessor in Spring Boot * BAEL-2569 add test * BAEL-2569 update test * BAEL-2569 refactoring the class PriceCalculationEnvironmentPostProcessor * BAEL-2569: changes to class PriceCalculationEnvironmentPostProcessor --- ...ceCalculationEnvironmentPostProcessor.java | 80 +++++++++++-------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java index 1b3099453e..ca6d6cc28f 100644 --- a/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java +++ b/spring-boot/src/main/java/com/baeldung/environmentpostprocessor/PriceCalculationEnvironmentPostProcessor.java @@ -1,71 +1,81 @@ package com.baeldung.environmentpostprocessor; +import static org.springframework.core.env.StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME; + +import java.util.Arrays; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; -import org.springframework.core.env.StandardEnvironment; -public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { +@Order(Ordered.LOWEST_PRECEDENCE) +public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor { private static final Logger logger = LoggerFactory.getLogger(PriceCalculationEnvironmentPostProcessor.class); - public static final int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE; - private int order = DEFAULT_ORDER; - private static final String PROPERTY_PREFIX = "com.baeldung.environmentpostprocessor."; - private static final String OS_ENV_PROPERTY_CALCUATION_MODE = "calculation_mode"; - private static final String OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE = "gross_calculation_tax_rate"; - private static final String OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE = "NET"; - private static final double OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE = 0; + private static final String PREFIX = "com.baeldung.environmentpostprocessor."; + private static final String CALCUATION_MODE = "calculation_mode"; + private static final String GROSS_CALCULATION_TAX_RATE = "gross_calculation_tax_rate"; + private static final String CALCUATION_MODE_DEFAULT_VALUE = "NET"; + private static final double GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE = 0; + + List names = Arrays.asList(CALCUATION_MODE, GROSS_CALCULATION_TAX_RATE); + + private static Map defaults = new LinkedHashMap<>(); + static { + defaults.put(CALCUATION_MODE, CALCUATION_MODE_DEFAULT_VALUE); + defaults.put(GROSS_CALCULATION_TAX_RATE, GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + } @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - PropertySource systemEnvironmentPropertySource = environment.getPropertySources() - .get(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); + PropertySource system = environment.getPropertySources() + .get(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME); - Map priceCalculationConfiguration = new LinkedHashMap<>(); - if (isActive(systemEnvironmentPropertySource)) { - priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), systemEnvironmentPropertySource.getProperty(OS_ENV_PROPERTY_CALCUATION_MODE)); - priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), systemEnvironmentPropertySource.getProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)); - } else { - logger.warn("System environment variables [calculation_mode,gross_calculation_tax_rate] not detected, fallback to default value [calcuation_mode={},gross_calcuation_tax_rate={}]", OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE, - OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); - priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_CALCUATION_MODE), OS_ENV_PROPERTY_CALCUATION_MODE_DEFAULT_VALUE); - priceCalculationConfiguration.put(key(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE), OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + Map prefixed = new LinkedHashMap<>(); + + if (!hasOurPriceProperties(system)) { + // Baeldung-internal code so this doesn't break other examples + logger.warn("System environment variables [calculation_mode,gross_calculation_tax_rate] not detected, fallback to default value [calcuation_mode={},gross_calcuation_tax_rate={}]", CALCUATION_MODE_DEFAULT_VALUE, + GROSS_CALCULATION_TAX_RATE_DEFAULT_VALUE); + prefixed = names.stream() + .collect(Collectors.toMap(this::rename, this::getDefaultValue)); + environment.getPropertySources() + .addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new MapPropertySource("prefixer", prefixed)); + return; } - PropertySource priceCalcuationPropertySource = new MapPropertySource("priceCalcuationPS", priceCalculationConfiguration); + prefixed = names.stream() + .collect(Collectors.toMap(this::rename, system::getProperty)); environment.getPropertySources() - .addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, priceCalcuationPropertySource); + .addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new MapPropertySource("prefixer", prefixed)); } - private String key(String key) { - return PROPERTY_PREFIX + key.replaceAll("\\_", "."); + private Object getDefaultValue(String key) { + return defaults.get(key); } - private boolean isActive(PropertySource systemEnvpropertySource) { - if (systemEnvpropertySource.containsProperty(OS_ENV_PROPERTY_CALCUATION_MODE) && systemEnvpropertySource.containsProperty(OS_ENV_PROPERTY_GROSS_CALCULATION_TAX_RATE)) { + private String rename(String key) { + return PREFIX + key.replaceAll("\\_", "."); + } + + private boolean hasOurPriceProperties(PropertySource system) { + if (system.containsProperty(CALCUATION_MODE) && system.containsProperty(GROSS_CALCULATION_TAX_RATE)) { return true; } else return false; } - public void setOrder(int order) { - this.order = order; - } - - @Override - public int getOrder() { - return order; - } - }

+ * You can find more information on how profiles work with JHipster on https://www.jhipster.tech/profiles/. + */ + @PostConstruct + public void initApplication() { + Collection activeProfiles = Arrays.asList(env.getActiveProfiles()); + if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) { + log.error("You have misconfigured your application! It should not run " + + "with both the 'dev' and 'prod' profiles at the same time."); + } + if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_CLOUD)) { + log.error("You have misconfigured your application! It should not " + + "run with both the 'dev' and 'cloud' profiles at the same time."); + } + } + + /** + * Main method, used to run the application. + * + * @param args the command line arguments + */ + public static void main(String[] args) { + SpringApplication app = new SpringApplication(BookstoreApp.class); + DefaultProfileUtil.addDefaultProfile(app); + Environment env = app.run(args).getEnvironment(); + logApplicationStartup(env); + } + + private static void logApplicationStartup(Environment env) { + String protocol = "http"; + if (env.getProperty("server.ssl.key-store") != null) { + protocol = "https"; + } + String serverPort = env.getProperty("server.port"); + String contextPath = env.getProperty("server.servlet.context-path"); + if (StringUtils.isBlank(contextPath)) { + contextPath = "/"; + } + String hostAddress = "localhost"; + try { + hostAddress = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException e) { + log.warn("The host name could not be determined, using `localhost` as fallback"); + } + log.info("\n----------------------------------------------------------\n\t" + + "Application '{}' is running! Access URLs:\n\t" + + "Local: \t\t{}://localhost:{}{}\n\t" + + "External: \t{}://{}:{}{}\n\t" + + "Profile(s): \t{}\n----------------------------------------------------------", + env.getProperty("spring.application.name"), + protocol, + serverPort, + contextPath, + protocol, + hostAddress, + serverPort, + contextPath, + env.getActiveProfiles()); + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/aop/logging/LoggingAspect.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/aop/logging/LoggingAspect.java new file mode 100644 index 0000000000..0379637061 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/aop/logging/LoggingAspect.java @@ -0,0 +1,98 @@ +package com.baeldung.jhipster5.aop.logging; + +import io.github.jhipster.config.JHipsterConstants; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; + +import java.util.Arrays; + +/** + * Aspect for logging execution of service and repository Spring components. + * + * By default, it only runs with the "dev" profile. + */ +@Aspect +public class LoggingAspect { + + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + private final Environment env; + + public LoggingAspect(Environment env) { + this.env = env; + } + + /** + * Pointcut that matches all repositories, services and Web REST endpoints. + */ + @Pointcut("within(@org.springframework.stereotype.Repository *)" + + " || within(@org.springframework.stereotype.Service *)" + + " || within(@org.springframework.web.bind.annotation.RestController *)") + public void springBeanPointcut() { + // Method is empty as this is just a Pointcut, the implementations are in the advices. + } + + /** + * Pointcut that matches all Spring beans in the application's main packages. + */ + @Pointcut("within(com.baeldung.jhipster5.repository..*)"+ + " || within(com.baeldung.jhipster5.service..*)"+ + " || within(com.baeldung.jhipster5.web.rest..*)") + public void applicationPackagePointcut() { + // Method is empty as this is just a Pointcut, the implementations are in the advices. + } + + /** + * Advice that logs methods throwing exceptions. + * + * @param joinPoint join point for advice + * @param e exception + */ + @AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e") + public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { + if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) { + log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(), + joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL", e.getMessage(), e); + + } else { + log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(), + joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL"); + } + } + + /** + * Advice that logs when a method is entered and exited. + * + * @param joinPoint join point for advice + * @return result + * @throws Throwable throws IllegalArgumentException + */ + @Around("applicationPackagePointcut() && springBeanPointcut()") + public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { + if (log.isDebugEnabled()) { + log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(), + joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs())); + } + try { + Object result = joinPoint.proceed(); + if (log.isDebugEnabled()) { + log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(), + joinPoint.getSignature().getName(), result); + } + return result; + } catch (IllegalArgumentException e) { + log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()), + joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName()); + + throw e; + } + } +} diff --git a/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/ApplicationProperties.java b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/ApplicationProperties.java new file mode 100644 index 0000000000..4ca3e9bd85 --- /dev/null +++ b/jhipster-5/bookstore-monolith/src/main/java/com/baeldung/jhipster5/config/ApplicationProperties.java @@ -0,0 +1,14 @@ +package com.baeldung.jhipster5.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Properties specific to Bookstore. + *